Делаем демон приложения в CentOS (Debian), работа с сервисами
В CentOS, в отличии от Ubuntu, по умолчанию нет Start-stop-daemon для запуска своих процессов в виде демонов. При его наличии запуск приложения в виде демона решается простой командой (главное чтобы скрипт был исполняемым :)).
start-stop-daemon -Sbvx /home/redkin_p/bin/test.rb
Для того чтобы сделать это в CentOS (справедливо и для Debian) есть такие варианты:
0) Запустить приложение через nohup. Или в сессии screen/tmux (о screen).
nohup — UNIX-утилита, запускающая указанную команду с игнорированием сигналов потери связи (SIGHUP). Таким образом, команда будет продолжать выполняться в фоновом режиме и после того, как пользователь выйдет из системы. Позволяет не запускать start-stop-daemon, делать сервисы и вообще что-либо. Идет из коробки во всех известных дистрибутивах Linux. Еще круто, что вывод она пишет в отдельный файл - nohup.out (если не нужен - можно дропнуть через редирект &>/dev/null) nohup bin/sms2.rb nohup nmap -sP 10.3.0.0/20 nohup ip netns exec VRF1 ping 172.17.0.2 >ping_res_va # по умолчанию STDOUT сохраняется в файле nohup.out
1) собрать start-stop-daemon для CentOS. Как по мне очень плохое решение (но, возможно, в 2011 единственное) – требует компилятора, компиляции и прочих штук очень долгих и несущих существенные изменений в систему (зависимые системные библиотеки).
2) Сделать сервис в system.d. Прекрасное решение. Немного сложнее start-stop-daemon (и, тем более, nohup), но лучше т.к. позволяет стандартно добавить сервис в автозагрузку, следить по аналогии с другими сервисами за работоспособностью, стандартно перезагружать и прочее.
https://scottlinux.com/2014/12/08/how-to-create-a-systemd-service-in-linux-centos-7/ https://unix.stackexchange.com/questions/236084/how-do-i-create-a-service-for-a-shell-script-so-i-can-start-and-stop-it-like-a-d
Пошагово создание сервиса в system.d
1) Создаем файл с сервисом, называем как хотим, на конце должно быть “service”.
$ cat /etc/systemd/system/test_service.service [Unit] Description=test_service.rb [Service] Type=simple ExecStart=/usr/bin/test_service.rb [Install] WantedBy=multi-user.target
Для передачи переменных (напр. указываем название файла вывода от времени запуска сервиса) можно вызывать утилиту через /bin/bash. Пример: запускаем tcpdump, имя файла с дампом содержит дату/время запуска.
ExecStart=/bin/bash -c "test=$(/usr/bin/date | tr ' :' '.'); /usr/sbin/tcpdump -n -w /opt/logs/$test.pcap"
2) Перезагружаем службу демонов
sudo systemctl daemon-reload
sudo systemctl start test_service
4) Проверяем статус. Тут так же видим последние сообщения от нашей программы/скрипта. Для просмотра всех сообщений смотрим journalctl.
sudo systemctl status test_service sudo journalctl -u test_service
5) Добавляем в автозагрузку (можно так же использовать множество других способов, напр. добавив команду start сервиса в /etc/rc.local, но самый правильный через systemctl; offtop: при использовании rc.local нужно не забывать добавлять shebang и права на исполнение)
sudo systemctl enable test_service
Leave a Reply Cancel reply
You must be logged in to post a comment.
start-stop-daemon
В этой статье будет рассмотрено использование start-stop-daemon . Данная утилита идет в составе dpkg и, следовательно, присутствует в любой системе на базе Debian/Ubuntu.
Ее функция следующая: она позволяет запустить любой процесс в виде демона, то есть в фоне. Это нужно для того, чтобы запускать в фоне те процессы, которые сами не умеют уходить в фон. Запуск процесса в виде демона позволит не держать постоянной открытой tty-консоль или вкладку в терминале, а также даст больше возможностей для контроля данного процесса.
Основы
Как упомянуто выше, основное предназначение — запуск программ в фоновом режиме. В качестве примера будет взят museekd , демон-клиент для p2p-сети soulseek. start-stop-daemon имеет два обязательных параметра: -S (или –start ) и -K ( –stop ), один из которых должен присутствовать в любой команде. Далее следуют параметры, указывающие, что и как запустить.
Запуск демона
Для того, чтобы запустить демон необходимо помимо ключа -S указать так же исполняемый файл – /usr/bin/museekd . Исполняемый файл задается ключом -x
start-stop-daemon -Sx /usr/bin/museekd
Однако, в фон программа не уйдет и вы увидите на экране ее вывод. Для того, чтобы процесс уходил в фон, нужно добавить ключ -b . Заодно добавьте ключ -v для отображения диагностических сообщений
start-stop-daemon -Sbvx /usr/bin/museekd
Программа запустится и будет работать в фоне. Для взятого примера этого достаточно.
Остановка демона
Для остановки процесса нужно указать ключ -K , т.е. действие «стоп», а так же сам процесс, который нужно остановить. Процесс для остановки так же указывается по исполняемому файлу, с помощью ключа -x
start-stop-daemon -Kvx /usr/bin/museekd
start-stop-daemon найдет процесс museekd и остановит его (по умолчанию — отправив SIGTERM).
Работа с pid-файлами
Если вы хотите запустить несколько копий одной программы, следует использовать pid-файлы 1) для управления такими процессами. Для запуска museekd с созданием pid-файла следует использовать ключ -p . Пример:
start-stop-daemon -Sbvmp $HOME/.museekd/pid -x /usr/bin/museekd
Здесь также появился ключ -m , указывающий утилите start-stop-daemon, что pid-файл нужно создать при запуске программы. Некоторые программы умеют создавать pid-файлы самостоятельно – в этом случае данный ключ не нужен.
Теперь в заданном файле записан PID запущенного процесса. Зная его, вы можете отличить его от других копий той же программы, найти процесс, к примеру, в top и сделать с ним что-либо (например, изменить приоритет или остановить).
Для остановки процессов также можно использовать pid-файлы, чтобы остановить конкретный процесс. При этом указание исполняемого файла не требуется, нужно лишь задать действие «стоп» и pid-файл
start-stop-daemon -Kvp $HOME/.museekd/pid
start-stop-daemon прочитает PID из заданного файла, проверит, есть ли такой процесс и остановит его.
Прочие возможности
Передача параметров запускаемой программе
Если запускаемой программе нужно передать какие-либо параметры, они отделяются двумя дефисами. Все, что идет далее, не воспринимается как параметры для start-stop-daemon, а передается запускаемой программе в неизмененном виде. Пример запуска museekd с альтернативным файлом конфигурации:
start-stop-daemon -Sbvmx /usr/bin/museekd -p $HOME/.museekd/pid -- -c .museekd/config.new
Данная конструкция запустит museekd -c .museekd/config.new . Двойной дефис и следующие за ним параметры не обязательно располагать после исполняемого файла. Главное – в конце комманды.
Утилита start-stop-daemon имеет гораздо больше возможностей, чем описано в данной статье. Например, она позволяет запустить процесс от имени другого пользователя или даже в chroot-окружении, задать приоритет процесса, изменить сигнал остановки (например, использовать SIGKILL вместо SIGTERM) и т. п. Больше информации можно получить из man start-stop-daemon и start-stop-daemon –help .
PID – это уникальный номер, по которому идентифицируется каждый запущенный в системе процесс. По PID можно отличить разные копии одной программы. pid-файл — это простой текстовый файл, в который записывается PID процесса. pid-файлы для некоторых системных процессов можно найти в /var/run
- Сайт
- Об Ubuntu
- Скачать Ubuntu
- Семейство Ubuntu
- Новости
- Форум
- Помощь
- Правила
- Документация
- Пользовательская документация
- Официальная документация
- Семейство Ubuntu
- Материалы для загрузки
- Совместимость с оборудованием
- RSS лента
- Сообщество
- Наши проекты
- Местные сообщества
- Перевод Ubuntu
- Тестирование
- RSS лента
© 2018 Ubuntu-ru — Русскоязычное сообщество Ubuntu Linux.
© 2012 Canonical Ltd. Ubuntu и Canonical являются зарегистрированными торговыми знаками Canonical Ltd.
Bash: запускаем демон с дочерними процессами
Доброго всем настроения!
Прочитал я вот эту статью, и решил немного сам взять в руки шашки, и попробовать сделать что-нибудь приятное для себя и для других.
Мой скрипт не делает никаких полезных вещей, но думаю для более менее начинающих писателей на bash он чему-нибудь научит, да и если будут комментарии, то и я научусь от тех людей которые укажут на мои ошибки.
Вводная
Скрипт будет запускаться в фоне демоном. Сразу думаю надо договориться что сам процесс который будет висеть в памяти постоянно я буду называть «Родителем». Родитель будет в определенном каталоге искать определенный файл, и если он существует, то файл будет удален и запущен процесс, который я буду называть «Потомок», целью которого будет просто спать какое-то время, и после чего завершиться. Но Родитель не должен будет запускать более одного Потомка в единицу времени. В принципе, если Вы прочитали вышеуказанную статью, то смысл я думаю понятен.
Начнем-с
# Имя файла который будем искать в каталоге FILE_NAME="run_Lola_run" # Каталог в котором будем искать файл WATCH_DIR="/home/mcleod/test" # Имя файла по которому будем определять запущен ли уже Родитель LOCK_FILE="$/monitor_file.lock" # Файл где будем хранить номер работающего процесса Родителя PID_FILE="$/monitor_file.pid" # Имя файла по которому будем определять запущен ли Потомок JOB_LOCK_FILE="$/job_monitor_file.lock" # В этот файл будем писать ход выполнения скрипта LOG="$/monitor_file_work.log" # В этот файл будут попадать ошибки при работе скрипта ERR_LOG="$/monitor_file_error.log" # Определяем максимельное время работы Потомка в секундах RANGE=100
Далее для удобного управления запуском и остановом Родителя напишем небольшое условие
case $1 in "start") start ;; "stop") stop ;; *) usage ;; esac exit
- start — функция запуска, которая переводит скрипт в режим демона
- stop — функция остановки демона
- usage — функция вывода на экран помощи
- _log — функция записи в лог файл
- run_job — функция запуска Потомка
Теперь опишу функции по мере их усложнения. Самая простая их них это функция usage, выглядит она так
# Функция остановки демона stop() < # Если существует pid файл, то убиваем процесс с номером из pid файла if [ -e $] then _pid=$(cat $) kill $_pid rt=$? if [ "$rt" == "0" ] then echo "Daemon stop" else echo "Error stop daemon" fi else echo "Daemon is't running" fi >
Здесь я не использую функцию логирования, т.к. здесь сообщения должны выводиться на консоль.
Теперь пожалуй приведу самую сложную функцию start. В ней находится вся логика работы и сам момент демонизации скрипта.
# Функция запуска демона start() < # Если существует файл с pid процесса не запускаем еще одну копию демона if [ -e $PID_FILE ] then _pid=$(cat $) if [ -e /proc/$ ] then echo "Daemon already running with pid = $_pid" exit 0 fi fi # Создаем файлы логов touch $ touch $ # переходим в корень, что бы не блокировать фс cd / # Перенаправляем стандартный вывод, вывод ошибок и стандартный ввод exec > $LOG exec 2> $ERR_LOG exec < /dev/null # Запускаем подготовленную копию процесса, вообщем форкаемся. Здесь происходит вся работа скрипта ( # Не забываем удалять файл с номером процесса и файл очереди при выходе trap "< rm -f $; exit 255; >" TERM INT EXIT # Основной цикл работы скрипта while [ 1 ] do # Просматриваем каталог на наличие файла if ls -1 $ | grep "^$$" 2>&1 >/dev/null then _log "parent" "File found" rm -f $/$ _log "parent" "File deleted" # Вычисляем сколько будет спать Потомок в секундах и запоминаем в массиве number=$RANDOM let "number %= $RANGE" _log "parent" "Genereated number $number" JOBS[$]=$number fi # Если размер массива больше 0, то запускаем Потомка, и удаляем первый элемент из массива if [ "$" -gt "0" ] then if [ ! -e $ ] then run_job _log "parent" "Running job with pid $!" unset JOBS[0] JOBS=("$") _log "parent" "Jobs in queue [$]" fi fi # Дадим процессору отдохнуть sleep 1 done exit 0 )& # Пишем pid потомка в файл, и заканчиваем работу echo $! > $ >
# Функция запуска Потомка. Потомок берет первый элемент из массива JOBS, и работает run_job() < # Здесь происходит порождение Потомка. Здесь уже ничего не подготавливаем и не переопределяем стандартный ввод/вывод, т.к. это уже сделано в Родителе ( # Не забываем удалять после окончания работы файл trap "< rm -f $; exit 255; >" TERM INT EXIT # Дополнительная проверка что бы убедиться что Потомок один if [ ! -e $ ] then # Пишем номер pid процесса в файл, на всякий случай echo "$$" > $ _log "child" "Job with pid $$" # Запоминаем первый элемент массива seconds=$ # Очищаем массив, хоть память сейчас и дешевая, но зачем ее занимать зря unset JOBS _log "child" "Sleep seconds $seconds" sleep $ else _log "child" "Lock file is exists" fi # Выходим exit 0 )& >
Ну и теперь если все вышеприведенное объеденить в файл и дать ему права на выполнение, думаю у Вас это не составит труда. Кстати перед запуском советую изменить значение переменной WATCH_DIR на путь к каталогу, в котором скрипт будет искать файл с именем run_Lola_run.
Вот мой вывод лог файла
parent[32338]: File found parent[32338]: File deleted parent[32338]: Genereated number 96 parent[32338]: Running job with pid 32385 parent[32338]: Jobs in queue [0] child[32338]: Job with pid 32338 child[32338]: Sleep seconds 96 parent[32338]: File found parent[32338]: File deleted parent[32338]: Genereated number 46 parent[32338]: File found parent[32338]: File deleted parent[32338]: Genereated number 1 parent[32338]: Running job with pid 32694 parent[32338]: Jobs in queue [1] child[32338]: Job with pid 32338 child[32338]: Sleep seconds 46 parent[32338]: Running job with pid 371 parent[32338]: Jobs in queue [0] child[32338]: Job with pid 32338 child[32338]: Sleep seconds 1
Надеюсь кому-нибудь данный пост поможет в освоении bash.
ЗЫ: Внимательный читатель наверняка увидел что в логе везде один и тот-же номер процесса. Т.к. в bash нет чистого форк, здесь происходит его, можно сказать, эмулирование через запуск необходимого кода в ()&, что запускает его в отдельном процессе, но при этом сохраняет переменные неизменными. А мы знаем что номер текущего процесса в bash хранится в переменной $$. Поэтому в лог файле и отображается один и тот же номер процесса. Именно поэтому функция start заканчивается строкой echo $! > $.