Pull to refresh

Debian Squeeze: параллельный автозапуск скриптов при старте системы

Введение


Я работаю в небольшой транспортной компании, занимаюсь администрированием зоопарка из win/linux машин. Выход нового дистрибутива Debian совпал с необходимостью внедрить несколько новых серверов на предприятии, точнее заменить старые работающие под win на новые под linux. Таким образом для внедрения был выбран Squeeze, я думал что управлюсь за день, но новый Debian, по мимо нового ПО, принес еще и сюрпризы.

Осознание проблемы


Утром я поставил систему, установил все необходимые пакеты, дальше начинаю прикручивать к системе скрипты (собственно сервер же заводим не для того чтобы им любоваться, а для работы). Сразу же уточню: cкрипт настраивал проксирование пользователей в интернет, все настройки он брал из PostgreSQL. Таким образом он должен запускаться после того как будет сконфигурирована сеть и запущен демон СУБД. И тут начинается мистика, создаю символическую ссылку на скрипт:

ln /usr/proxy/scripts/start /etc/rc1.d/S99proxy
ln /usr/proxy/scripts/start /etc/rc2.d/S99proxy
ln /usr/proxy/scripts/start /etc/rc3.d/S99proxy
ln /usr/proxy/scripts/start /etc/rc4.d/S99proxy
ln /usr/proxy/scripts/start /etc/rc5.d/S99proxy


Перезагружаю сервер, и обнаруживаю что скрипт не запустился, во всяком случае нужных мне действий произведено не было. Начинаю хмуриться, в это время вспоминаю о статье, которую читал несколько дней назад. Помещаю симлинк в другое место:

ln /usr/proxy/scripts/start /etc/network/if-up.d/proxy

Перезагружаю систему, скрипт начинает выполняться, но снова провал. Скрипт настройки сети запускается раньше чем стартует демон СУБД, и соответственно содержимое /etc/network/if-up.d выполняется тоже раньше (собственно оно так и должно быть). Далее решаю поместить в директории rc*.d скрипт со следующим содержанием:

#!/bin/bash
echo "Run test" >> /var/log/test.log


Снова перезагружаю систему, результат нулевой. Помня все туже статью, в голову приходи дикая мысль о том что локальная файловая система не успела примонтироваться. Применяю метод админа-шамана:

#!/bin/bash
sleep 20
echo "Run test" >> /var/log/test.log


После перезагрузки обнаруживаю отсутствие файла /var/log/test.log. От такого облома я решаю схитрить — дописываю в скрипт запуска демона ssh строку с echo. После перезагрузки как и полагается обнаружил то что ждал, файл создался и строчка «Run test» в нем присутствует. Начинаю активно шевелить мозгами, в уме появляется уравнение: запуск скрипта не работает + новая система запуска скриптов при старте системы = неожиданное поведение. Вывод напрашивается один: надо гуглить искать решение в технических статьях и документации.

Вот где собака зарыта


В ходе исследования было выяснено что в Debian Squeeze используется система LSBInitScripts для запуска скриптов при загрузке ОС. Ее особенностью является — по возможности параллельный запуск скриптов. В предыдущем предложении слова «по возможности» являются ключевыми. Нельзя просто взять и параллельно запустить все скрипты, часть скриптов имеет определенные зависимости от других служб. В моем случае скрипт должен выполняться только после запуска СУБД и настройки сети. Для этого LSBInitScripts строит граф зависимостей. Его графическое представление можно увидеть выполнив команды:

aptitude install insserv graphviz
/usr/share/insserv/check-initd-order -g > boot.dot
dotty boot.dot


В моем случае это получилась полнейшая кракозябра. Встал вопрос о том где же хранятся эти зависимости. В вики Debian'на выяснилось, что зависимости указываются в комментариях у скриптов в директории /etc/init.d, вот пример такого комментария для ssh:

### BEGIN INIT INFO
# Provides: sshd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: OpenBSD Secure Shell server
### END INIT INFO


Provides — это имя или несколько имен того с чем работает(запускает/останавливает) скрипт. Имена должны быть уникальны.
Required-Start— а вот это как раз и есть наша зависимость, которая указывает что потребуется скрипту для запуска.
Default-Start — показывает на каких уровнях нужно выполнять загрузку скрипта.
Более детальное описание параметров есть здесь.

Создаем свой скрипт


Теперь, когда мы знаем нашего врага в лицо можно попробовать написать пару простеньких скриптов. Вот первый, назовем его test:

#!/bin/sh

### BEGIN INIT INFO
# Provides: test-service
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Test-service
### END INIT INFO

echo "Run test" >> /var/log/test.log


Вот второй:
#!/bin/sh

### BEGIN INIT INFO
# Provides: test2-service
# Required-Start: $local_fs test-service
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Test-service
### END INIT INFO

echo "Run test2" >> /var/log/test.log


Файлы называются test и test2 соответственно. В данном примере test2 зависит от test, и поэтому test будет запускаться первым, а затем только test2. Поместим их в директорию /etc/init.d. Но этого еще мало, и даже мало будет создания симлинков в /etc/rc*.d. Что бы заставить все это дело работать необходимо выполнить построение нового графа зависимостей, делается это командами:

update-rc.d test defaults
update-rc.d test2 defaults


На полное изучение документации команды update-rc.d пока времени не было. Данная команда переписывает файлы .depend.boot, .depend.start, .depend.stop (это файлы с графом зависимостей, хранятся в /etc/init.d) и создает все нужные симлинки в /etc/rc*.d. Теперь пробуем перезагрузиться, и обнаруживаем что скрипты выполнились. И не просто выполнились абы как, а в определенной последовательности. Если поменять зависимость между test и test2 на обратную то и загрузятся они по другому.

Со своим скриптом я больше сегодня не экспериментировал — голова уже начала плохо думать и время рабочее закончилось, займусь им завтра.

Заключение


В данной статье я не пытался полностью описать новый процесс запуска скриптов в Debian. Моей целью было дать отправную точку для изучения проблемы, сэкономить время других людей (у меня ушло несколько часов на поиск причины, чтение манов и эксперименты).

Источники которыми я пользовался


citforum.ru/news/25677
www.opennet.ru/opennews/art.shtml?num=23318
wiki.debian.org/LSBInitScripts/DependencyBasedBoot
wiki.debian.org/LSBInitScripts
man update-rc.d
man insserv
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.