«Правильный» способ запуска сценария оболочки в качестве демона

20

Я пишу скрипт , который я хотел бы работать в качестве демона при запуске без использования внешних инструментов , таких как DaemonTools или демон .


Linux Daemon Writing HOWTO

Согласно Linux Daemon Writing HOWTO , правильный демон имеет следующие характеристики:

  • вилки из родительского процесса
  • закрывает все файловые дескрипторы (то есть stdin, stdout, stderr)
  • открывает логи для записи (если настроено)
  • изменяет рабочий каталог на постоянный (обычно /)
  • сбрасывает маску режима файла (umask)
  • создает уникальный идентификатор сеанса (SID)

Демонизация Введение

Демон Введение идет дальше, утверждая , что типичный демон также:

  • отсоединяется от терминала управления (если таковой имеется) и игнорирует все сигналы терминала
  • отделяется от своей группы процессов
  • ручки SIGCLD

Как бы сделать все это в sh, dashили bashсценарий только с общими инструментами Linux?

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


ПРИМЕЧАНИЕ. Я знаю, что в сети StackExchange есть множество ответов, в которых рекомендуется использовать nohupили setsid, но ни один из этих методов не отвечает всем вышеперечисленным требованиям.


EDIT: демон (7) страница руководства также дает некоторые указатели, хотя , кажется, некоторые различия между старым стилем SysVдемонами и новыми из systemdних. Поскольку совместимость с различными дистрибутивами важна, пожалуйста, убедитесь, что ответ проясняет любые различия.


user339676
источник
1
«Правильный» способ создания собственного сценария оболочки состоит в том, чтобы заставить его вести свою собственную регистрацию, предоставить метод для запуска его в качестве демона и т. Д. Такие вещи daemonи другие вещи предназначены для запуска произвольных сценариев оболочки без предоставления возможности запуска как демон. Поскольку вы автор, полностью контролирующий, как пишется этот скрипт, сделайте так, чтобы его можно было просто запустить из файла systemd unitfile или rc.d. Вы же указать «Правильные»!
Богатое

Ответы:

16

Используя systemd, вы сможете запустить скрипт как демон, создав простой модуль. Вы можете добавить множество различных опций , но это настолько просто, насколько вы можете получить.

Скажем, у вас есть сценарий /usr/bin/mydaemon.

#!/bin/sh

while true; do
  date;
  sleep 60;
done

Вы создаете юнит /etc/systemd/system/mydaemon.service.

[Unit]
Description=My daemon

[Service]
ExecStart=/usr/bin/mydaemon
Restart=on-failure

[Install]
WantedBy=multi-user.target 

Чтобы запустить демона, ты бежишь

systemctl start mydaemon.service 

Для запуска при загрузке вы включаете его

systemctl enable mydaemon.service

Если в системе, основанной на systemd, которой сегодня является большинство дистрибутивов Linux, это на самом деле не внешний инструмент. Негатив будет то, что он не будет работать везде, хотя.

johnramsden
источник
3
В то время как мне нравится системный подход, OP сказал, что «никаких внешних инструментов». Есть дистрибутивы Linux, в которых еще нет systemd, или вы можете выбирать между systemd и чем-то еще, например OpenRC.
Кристиан Чиупиту
5
Для дистрибутивов, которые используют systemd, systemdэто не более «внешний инструмент», чем bash.
Александр
7

Я, наверное, что-то здесь упускаю; почему именно не nohupподойдет? Конечно , это не достаточно , в одиночку , но в дополнение к нему кажется простым.

#!/bin/bash

if [ "$1" = "DAEMON" ]; then
    # is this necessary? Add other signals at will (TTIN TTOU INT STOP TSTP)
    trap '' INT
    cd /tmp
    shift
    ### daemonized section ######
    for i in $( seq 1 10 ); do
        date
        sleep 5
    done
    #### end of daemonized section ####
    exit 0
fi

export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin
umask 022
# You can add nice and ionice before nohup but they might not be installed
nohup setsid $0 DAEMON $* 2>/var/log/mydaemon.err >/var/log/mydaemon.log &

Насколько я вижу:

  • выходные данные соответствующим образом перенаправляются (при необходимости используйте / dev / null)
  • Маска наследуется
  • stdin умирает в конце родительского сценария, однако
  • сценарий daemon.sh переставляется в init(или systemd)

У меня сильное чувство, что я упускаю очевидное. Downvote, но, пожалуйста, скажите мне, что это такое :-)

LSerni
источник
2
Я собирался предложить что-то очень похожее. Я использую перенаправление nohupс &и I / O для запуска нескольких Cутилит, не являющихся демонами, возможно, с дополнительной защитой, заключающейся в переносе вашей nohupкоманды в a su -c "nohup ... &" -s /bin/bash systemUserдля запуска демона как непривилегированного пользователя.
111 ---
4

Команда Linux, screenсодержащаяся в большинстве дистрибутивов, может демонизировать скрипт оболочки. Я использую это часто. Вот быстрый пример, чтобы начать, перечислить и выйти из отдельного сеанса экрана ...

# screen -dmS Session_Name  bash -c "while true; do date; sleep 60; done"

# screen -ls
There are screens on:
        8534.Session_Name       (04/04/2018 08:46:27 PM)        (Detached)

# screen -S Session_Name -X quit
S.Haran
источник
2
screenне отключает скрипт оболочки. Он просто запускает их в выделенном терминале и может отсоединиться от этого терминала (например, отключить клавиатуру от ПК), не закрывая сеанс. Итак, программа, запущенная в отдельном терминале, работает в фоновом режиме. Поэтому - отсоедините программу прохода в фоновом режиме.
Юрий Гончарук