Демонизация приложений, делаем демон приложения в CentOS (Debian), работа с сервисами systemctl

  • systemctl (system control) без запущенных аргументов выдает список сервисов/демонов, запущенных в системе
root@serv:~# systemctl
UNIT LOAD ACTIVE SUB DESCRIPTION 
proc-sys-fs-binfmt_misc.automount loaded active waiting Arbitrary Executable File Formats File System Automount Point 
sys-devices-pci0000:00-0000:00:07.1-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device loaded active plugged VMware_Virtual_IDE_CDROM_Drive 
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda1.device loaded active plugged Virtual_disk 1 
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda2.device loaded active plugged Virtual_disk 2 
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda5.device loaded active plugged Virtual_disk 5 
sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda.device loaded active plugged Virtual_disk 
sys-devices-pci0000:00-0000:00:11.0-0000:02:00.0-net-ens32.device loaded active plugged 82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter)
sys-devices-pci0000:00-0000:00:11.0-0000:02:01.0-net-ens33.device loaded active plugged 82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter)
sys-devices-pci0000:00-0000:00:11.0-0000:02:02.0-net-ens34.device loaded active plugged 82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter)
sys-devices-platform-floppy.0-block-fd0.device loaded active plugged /sys/devices/platform/floppy.0/block/fd0 
...
Все управляющие программы для роботов по сути демоны/службы - работают в бесконечном цикле.

В CentOS, в отличии от Ubuntu, по умолчанию нет Start-stop-daemon для запуска своих процессов в виде демонов. При его наличии запуск приложения в виде демона решается простой командой (главное чтобы скрипт был исполняемым :)).

start-stop-daemon -Sbvx /home/redkin_p/bin/test.rb

Для того чтобы сделать это в CentOS (справедливо и для Debian) есть такие варианты:

0) screen

1) Запустить приложение через 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

2) собрать start-stop-daemon для CentOS. Как по мне очень плохое решение (но, возможно, в 2011 единственное) – требует компилятора, компиляции и прочих штук очень долгих и несущих существенные изменений в систему (зависимые системные библиотеки).

3) Перевести активное приложение/процесс с отвязкой от терминала можно с использованием hotkey по сворачиванию + переводу в background + disown процеса

1) Ctrl+Z to stop (pause) the program and get back to the shell.
2) bg to run it in the background.
3) disown -h [job-spec] where [job-spec] is the job number (like %1 for the first running job; find about your number with the jobs command) so that the job isn't killed when the terminal closes.

Команда disown является встроенной командой таких командных оболочек, как Bash, Zsh и Ksh и позволяет убрать заданную задачу из таблицы задач командной оболочки. Это делается для того заблокировать отправку системного сигнала SIGHUP запущенному с помощью командной оболочки и исполняющемуся в фоновом режиме процессу при завершении работы командной оболочки. В отличие от команды nohup, рассматриваемая команда может использоваться в любой момент после создания задачи, а не до только при ее создании и не отсоединяет стандартные потоки ввода, вывода и ошибок исполняющегося процесса от командной оболочки.

4) Сделать сервис в 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

3) Стартуем наш сервис

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 и права на исполнение). Флаг –now позволяет запустить службу, даже если ранее мы ее не запустили через start.

sudo systemctl enable test_service
sudo systemctl enable --now open-vm-tools

Enjoy

 

 

Типы сервисов в system.d

Выше рассмотрен простой типовой случай, когда используется тип сервиса simple, но возможно так же использовать oneshot и forking.

  • Forking: systemd считает службу запущенной после того, как процесс разветвляется с завершением родительского процесса. Нужен для работы с приложениями, которые создают дочерние процессы при запуске (напр. worker’ы), а сами при этом отключаются – используется для запуска классических демонов за исключением тех случаев, когда в таком поведении процесса нет необходимости. Можно указать параметр PIDFile=, чтобы systemd мог отслеживать основной процесс. Oneshot и forking для таких задач подходят плохо, они оба предназначены для работы именно с тем процессом, который запускается
Both Type=oneshot and Type=simple units ignore any children of the first process, so do not use these modes with forking processes
  • Simple (по умолчанию): systemd запустит эту службу незамедлительно. Процесс при этом не должен разветвляться (fork). Если после данной службы должны запускаться другие, то этот тип использовать не стоит (исключение — служба использует сокетную активацию).
  • Oneshot: удобен для сценариев, которые выполняют одно задание и завершаются. Примеры использования.
Если задать параметр RemainAfterExit=yes, то systemd будет считать процесс активным даже после его завершения.

Leave a Reply