| « Поставить закладку » « Сделать стартовой » | |||
|
|||
|
О запуске нескольких разных InterBase в Linux
Общие принципыВо-первых, о применимости данного опыта. Я говорю о Linux, потому что я именно на нём это дело испытывал. Конкретно -- на Slackware 7.1 с доустановленными обновлениями из Slackware-current. Однако на самом деле подобные сооружения должны работать на любой версии любой юниксообразной системы. Главное, чтобы в этой системе работал InterBase и chroot. Во-вторых, я пробовал виртуализовать только Classic. Есть мысли о том, как это можно сделать в Super, изложены ниже. Итак, создав в файловой системе ветку, по структуре напоминающую систему в целом, и содержащую файлы, необходимые для запуска нужного приложения, можно создать для него виртуальную среду, достаточно сильно изолированную от остальной части системы. В этой среде с помощью системного вызова chroot или одноимённой команды можно запускать нужные процессы, видящие в качестве корня только свою ветку. Этот изменённый корень наследуется процессами, так что выйти за его пределы они обычно не могут. Тут же замечу, что хотя chroot и способствует усложнению взлома системы со стороны процессов, работающих в ``защищённой'' среде, тем не менее полных гарантий сам по себе не даёт. Особенно если в рамках среды chroot существуют процессы с правами root, есть программы suid, и т. п. Список требований достаточно длинный, и к сожалению никто не может поручиться, что полный. Так что безопасность -- вообще отдельный вопрос, который мы сейчас не рассматриваем. В системе одновременно может функционировать сколько угодно виртуальных сред на основе chroot. Точнее -- столько, на сколько хватит ресурсов. При этом в разных средах может быть установлен разный софт разных версий. Главное, чтобы он нормально взаимодействовал с ядром системы, так как оно у всех общее. К счастью, в Linux системные вызовы в последние годы существенно не менялись, особенно в той части, которая нужна для InterBase. И версии libc разных поколений с текущими ядрами вполне нормально уживаются. В моём случае было ядро 2.2.18, libc 5.4.46 в ветке для InterBase 4.0, glibc 2.2.1 во всех. И последний из теоретических вопросов -- как поделить между серверами сеть. Ведь клиенты ожидают, что в сервере будет работать только один InterBase, и он должен ``слушать'' знаменитый порт 3050. Проблема решается навешиванием на сетевой интерфейс машины нескольких адресов IP, которым через hosts/DNS присваиваются разные имена. Далее пишется небольшая программка (у меня был скрипт на Perl), которая в зависимости от адреса, на который пришло соединение, делает chroot в нужную среду, и запускает там местный gds_inet_server.
Как это былоВообще надо сказать, что для таких операций, как создание веток файловой системы под chroot, запуска различных команд из inetd в зависимости от адреса соединения, и т. п., существуют готовые инструменты. Однако в те дни, когда я это делал, на солнце были вспышки, спутниковая тарелка, через которую у нас Инет, глючила всеми возможными способами, да и просто было лениво ``вылезать наружу''. Тем более что самопальные решения оказались не такими уж и сложными. Итак, понадобилось тестировать разрабатываемый софт с разными версиями IB. А так же средство для конвертации баз между разными ODS через backup-restore. Для установки были выбраны дистрибутивы:
Первым делом нужно было сформировать сами виртуальные среды. Я начал с того, что сформировал ``пустышку'', в которой были набросаны файлы, минимально необходимые для запуска инсталятора всего остального. В Slackware -- installpkg из пакета hdsetup.tgz. Понадобились каталоги /bin, /sbin, /lib (часть крупных, но ненужных файлов выкинул), /tmp (пустой), кое-что из /var. Выяснял методом тыка, периодически запуская что-нибудь наподобие chroot виртуальный-корень /sbin/installpkg /bash.tgz, и выясняя, чего ему ещё не хватает. Сам bash.tgz, естественно, тоже пришлось положить в ту самую ветку, чтобы он был виден изнутри. После того, как инсталятор в виртуальной среде ожил, тем же путём (то есть закидыванием пакета в каталог, и запуском инсталятора ``внутри'' были поставлены aaa_base, bin, elflibs, etc, fileutils, find, glibcso, grep, gzip, hdsetup (для чистоты), ldso, perl, tar, txtutils, util, zoneinfo. Полученная ветка файловой системы была заархивирована и использовалась впоследствии в качестве заготовки. С ней было снято три копии, под три варианта InterBase. В каждую копию был положен соответствующий дистрибутив, после чего делалось chroot виртуальный-корень /bin/bash и в получившейся комстроке делалась обычная установка. Инсталятор обновлял /etc/services и /etc/inetd.conf, которые видел, и которые к реальному функционированию системы отношения не имели. При этом иногда возникали небольшие проблемы, что чего-то не хватало. В этом случае я либо дописывал файлы из основной системы, либо доставлял пакеты. К сожалению, не всё фиксировал, так что точно перечислить теперь затрудняюсь, но при надлежащем знании своей системы это выяснить несложно. В заключение установок каждой ветки создавался каталог /database (в соответствующей ветке) и ему настраивались права для логина interbase. Сам логин был руками внесён в /etc/passwd и /etc/shadow каждой ветки, но исходно был создан в основной системе. При таких копированиях важно проследить, чтобы один и тот же пользователь везде получил один и тот же номер uid. Кроме этого были сняты атрибуты suid и sgid со всех файлов в ветках chroot. На всякий случай. После того, как локальные подключения в пределах каждого chrootбыли
проверены на работоспособность, я перешёл к сетевой части. Во-первых, были
изготовлены дополнительные адреса, и навешаны через Далее был написан скрипт. Привожу то, что возникло в результате отладки. #!/usr/bin/perl
# (C) Dmitri Popov, 2001
# Freeware
use Socket;
my $sockaddr = getsockname(STDIN);
exit if ! $sockaddr;
open(LOGSTREAM, '>>/var/log/gdsconnect');
my ($port, $addr) = sockaddr_in($sockaddr);
$addr = inet_ntoa($addr);
dolog("addr=$addr");
runserver('/roots/ib5', '/usr/interbase')
if( $addr eq '192.168.1.251' );
runserver('/roots/fb', '/opt/interbase')
if( $addr eq '192.168.1.252' );
runserver('/roots/ib4', '/usr/interbase')
if( $addr eq '192.168.1.253' );
exit 133; # паранойя
sub runserver
{ my $root = shift;
my $base = shift;
dolog("root=$root, base=$base");
chdir($root);
chroot($root);
exec( "/bin/su interbase -c"
. "$base/bin/gds_inet_server");
}
sub dolog
{ my $str = shift;
printf LOGSTREAM "%s %sn",
scalar localtime(), $str;
}
Замечания
Ну и последняя операция состояла в том, чтобы запускать этот скрипт из inetd. Перед этим необходимо обеспечить наличие gds_db в глобальном /etc/services, если его там ещё нет. Содрать можно с любого результата установки в chroot. Непосредственно в (глобальный!) inetd.conf пошла строчка: gds_db stream tcp nowait.100 root /usr/sbin/tcpd /usr/local/sbin/gdsconnect Обратите внимание -- запуск идёт от рута. Это необходимо для того, чтобы сработал chroot. Переключение на interbase производится уже после. Конечно, заработало не сразу. Приходилось вставлять в скрипт вызовы dolog() с подробностями. Большинство из них из окончательной версии удалены.
|
Цитата дня (все,добавить):
|
Realcoding.NET
© 2003-2008 |
Контакты |
Реклама на сайте
|