Как я могу зарегистрировать stdout процесса, запущенного start-stop-daemon?

Я использую init script для запуска простого процесса, который начинается с:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS

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

Я хотел бы написать или добавить stdout из $DAEMON в файл где-нибудь.

Единственное решение, которое я знаю, - сообщить start-stop-daemon для вызова shellscript вместо $DAEMON напрямую; script затем вызывает $DAEMON и записывает в файл журнала. Но для этого требуется дополнительный script, который, как и изменение самого демона, кажется неправильным способом решения такой общей задачи.

Ответ 1

Чтобы расширить ответ на ypocat, так как он не позволит мне прокомментировать:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
 --make-pidfile --pidfile $PIDFILE --background       \
 --startas /bin/bash -- -c "exec $DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Использование exec для запуска демона позволяет остановить правильную остановку дочернего процесса, а не только родителя bash.

Использование --startas вместо --exec гарантирует, что процесс будет правильно обнаружен его pid и не будет ошибочно запускать несколько экземпляров демона, если start вызывается несколько раз. В противном случае, start-stop-daemon будет искать процесс /bin/ bash и игнорировать фактический дочерний процесс, запускающий демона.

Ответ 2

Вам нужно сделать:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec /bin/bash -- -c "$DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Также, если вы используете --chuid или --user, убедитесь, что пользователь может написать /var/log или существующий /var/log/some.log. Лучший способ состоит в том, чтобы у этого пользователя был /var/log/subdir/.

Ответ 3

Кажется, вы должны теперь использовать параметр --no-close при запуске start-stop-daemon для захвата вывода демона. Эта новая функция доступна в пакете dpkg с версии 1.16.5 на Debian:

Добавить новую опцию --no-close для отключения закрытия fds на -background.

Это позволило вызывающему абоненту видеть сообщения процесса для отладки целей или иметь возможность перенаправлять файловые дескрипторы на файлы журналов, syslog или аналогичный.

Ответ 4

С openrc (который по умолчанию используется для gentoo или alpine linux) start-stop-daemon имеет параметры -1 и -2:

-1, --stdout Перенаправить stdout в файл

-2, --stderr Перенаправить stderr в файл

Итак, вы можете просто написать:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS -1 $LOGFILE -2 $LOGFILE

Ответ 5

Не сложно записать вывод демон и сохранить его в файл:

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas $DAEMON --no-close \
  -- $DAEMON_ARGS >> $LOGFILE 2>&1

Однако это решение может быть субоптимальным для logrotate.

Может быть лучше захватить вывод в syslog. На Debian это будет соответствовать поведению системных служб. Следующая простая попытка переписать вышеприведенный пример неверна, поскольку она оставляет за собой два родительских ( "зомби" ) процесса (регистратор и демон) после остановки демона, потому что start-stop-daemon завершает только его дочерний элемент, но не все потомки:

## Do not use this!
start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /bin/sh \
  -- -c """exec $DAEMON $DAEMON_ARGS | /usr/bin/logger --tag $NAME"""

Чтобы сделать это, нам нужна оболочка, которая завершает свои дочерние элементы после получения SIGTERM от start-stop-daemon. Есть несколько:

duende:
start-stop-daemon --start --background \
  --pidfile $PIDFILE \
  --startas /usr/sbin/duende \
  -- --pid $PIDFILE --chroot=/ --uid 65534 --ident $NAME \
  /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec ${DAEMON} $DAEMON_ARGS"""

Примечание: uid=65534 является пользователем nobody.

Плюсы: он работает, и это относительно легко.
Минусы: 4 процесса (супервизор duende, его вилка с привилегиями сброса (logger), su и сам демон); обязательный --chroot; Если демон немедленно завершает работу (например, неверная команда) status_of_proc -p $PIDFILE "$DAEMON" "$NAME" сообщит об этом как успешно запущенный.

daemon:
start-stop-daemon --start --pidfile $PIDFILE \
  --startas /usr/bin/daemon \
  -- --noconfig --name $NAME --stderr=syslog.info --stdout=syslog.info \
  -- /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec $DAEMON $DAEMON_ARGS"""

Плюсы: 3 процесса (супервизор daemon, su и сам демон).
Минусы: трудно управлять $PIDFILE из-за путаницы параметров командной строки daemon; Если демон немедленно завершает работу (например, неверная команда) status_of_proc -p $PIDFILE "$DAEMON" "$NAME" сообщит об этом как успешно запущенный.

pipexec (победитель):

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /usr/bin/pipexec -- -k \
   -- [ D $DAEMON $DAEMON_ARGS ] [ L /usr/bin/logger --tag $NAME ] '{D:2>D:1}' '{D:1>L:0}'

Плюсы: 3 процесса (супервизор pipexec, logger и сам демон); Если демон немедленно завершает работу (например, неверная команда) status_of_proc -p $PIDFILE "$DAEMON" "$NAME" правильно сообщает об ошибке.
Минусы: нет.

Это победитель - самое простое, опрятное решение, которое, кажется, хорошо работает.

Ответ 6

Указание старого списка рассылки:

https://lists.ubuntu.com/archives/ubuntu-uk/2005-June/000037.html

Легко - и если вы хотите использовать start-stop-daemon, возможно, единственный способ вокруг него нужно создать небольшой script содержащий:

#!/bin/sh
exec /home/boinc/boinc/boinc > /home/boinc/log/boinc.log

а затем используйте этот script как аргумент для запуска-остановки-демона.

Возможно, реальный вопрос заключается в том, действительно ли необходимо использовать start-stop-daemon в первую очередь?

Ответ 7

Я не уверен, что "$ DAEMON $DAEMON_ARGS > /var/log/some.log 2 > & 1" когда-нибудь закроет дескриптор файла для файла журнала... что означает, что ваш демон запускается вечно, Я не уверен, что логротат или другие механизмы для очистки дискового пространства будут работать. Поскольку он > вместо → , предлагаемая команда также будет обрезать существующие журналы при перезапуске. Если вы хотите узнать, почему демон врезан, и он автоматически перезагружается, это может быть не очень полезно.

Другим вариантом может быть "$ DAEMON | logger". logger - это команда, которая будет регистрироваться в syslog (/var/log/messages). Если вам тоже нужен stderr, я думаю, вы могли бы использовать "$ DAEMON 1 > & 2 | logger"

Ответ 8

Обычно start-stop-daemon закрывает стандартные дескрипторы файлов при работе в фоновом режиме. На странице руководства start-stop-daemon:

-C, --no-close
 Не закрывайте дескриптор файла при принуждении демона к фону. Используется для отладки, чтобы увидеть               выход процесса или перенаправление файловых дескрипторов для регистрации вывода процесса. Используется только при использовании --background.

Это работало для меня:

    start-stop-daemon -b -C -o -c \ 
         $DAEMON_USER -S -x $DAEMON > $DAEMON_LOG 2>&1

Ответ 9

Предполагая, что это bash (хотя некоторые другие оболочки также могут это допускать), строка:

exec >>/tmp/myDaemon.log

отправит в этот файл весь будущий стандартный вывод. Это потому, что exec без имени программы просто выполняет некоторую магию перенаправления. На странице bash man:

Если команда не указана, любые перенаправления вступают в силу в текущей оболочке.

Управление указанным файлом - это еще одна проблема.

Ответ 10

Как насчет:

sudo -u myuser -i start-stop-daemon ...