Як я можу зареєструвати stdout процесу, розпочатого запуском-стоп-демон?


120

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

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

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

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

Єдине мені відоме рішення - сказати старт-стоп-демону викликати оболонку оболонки замість $ DAEMON безпосередньо; Потім скрипт викликає $ DAEMON і записує в лог-файл. Але для цього потрібен додатковий скрипт, який, як і зміна самого демона, здається неправильним способом вирішення такої загальної задачі.

Відповіді:


127

Щоб розширити відповідь 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для запуску демон дозволяє зупинити, щоб правильно зупинити дочірній процес, а не просто батьків-баш.

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


2
Це набагато краще рішення , ніж один з @ypocat головним чином тому , закриваючи демон знову, замінивши --startв --stopнасправді працює.
aef

Я спробував запустити цю команду з rc.local замість init.d ... Я, здається, не отримував однакових результатів. Однак при запуску з оболонки через SSH це працює як шарм!
nemo

1
Як би start-stop-daemon --test (...)виглядало супутнє ?
Абдулл

2
@MattClimbs Він перезаписує файл після кожного запуску. використовувати >>замість >додавання.
Мяу

2
Перш ніж ви вигадаєте (як я), тому що ваш журнал порожній, пам’ятайте, що це буфер! Ви можете використовувати "exec stdbuf -oL -eL $ DAEMON $ DAEMONARGS> $ LOGFILE 2> & 1", щоб змусити вихід вимикати кожен рядок (з blog.lanyonm.org/articles/2015/01/11/… )
piers7

47

Вам потрібно зробити:

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/.


1
Фантастичний, дякую ypocat. Сьогодні, як і для збереження журналу, мені потрібно було запустити небінарний скрипт, який --exec не дозволяє, але ваш трюк працює навколо!
joeytwiddle

8
Нижня сторона ... припинення послуги вбиває баш, але не почався дитячий процес! (У моєму випадку DAEMON = кава).
joeytwiddle

1
Я працював над цим, вбиваючи всі дочірні процеси баш-процесу у верхній частині do_stop. bashPID=$(cat $PIDFILE); [ -n "$bashPID" ] && pkill -P "$bashPID"
joeytwiddle

5
Добре знати, і pkillрішення теж. Цікаво, що б зробити ... -c "exec $DAEMON..."(додавши "exec"). Не майте цього на тарілці зараз, тому не можу спробувати.
youurayy

12
@ypocat Я щойно перевірив, що він працює з -c "exec $ DAEMON ...". Це означає, що не потрібні хакі на ПК.
перемогти

40

Здається, ви повинні мати можливість використовувати цей --no-closeпараметр, коли починаєте start-stop-daemonфіксувати вихід демона. Ця нова функція доступна в dpkgпакеті з версії 1.16.5 на Debian:

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

Це дало можливість абоненту переглядати повідомлення процесу для цілей налагодження або мати можливість перенаправляти дескриптори файлів на журнали файлів, syslog або подібні.


8
Прикро, що вона недоступна в Ubuntu 12.04 :(
Леон Радлі,

Я не можу здатися, що це - не близько до роботи ... висновок все ще йде до оболонки, яку я
виконую

+1 Відмінно працює на стисканні Debian за допомогою демонзованого сервісу node.js.
доповідач

2
@stantonk Ви також передавали файл stdout / stderr у файл? Повний командний рядок виглядає наступним чином. І переконайтесь, що логічний файл може бути записаний користувачем $ USER: start-stop-daemon --start --chuid $ USER --pidfile $ PIDFILE --background --no-close - make-pidfile --exec $ DAEMON - $ DAEMONARGS >> /var/log/xxxxx.log 2> & 1
nharrer

1
Це недоступно для openrc start-stop-daemon. Однак у версії openrc є -1і -2варіанти перенаправлення stdout і stderr відповідно.
маленький чувак

14

У openrc (який є типовим для gentoo або альпійського 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

9

Зробити вихід демона і зберегти його у файл не надто важко:

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. Є кілька:

дуенде :
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, його вилка зі скинутими привілеями (реєстратор) suта сам демон); обов'язкові --chroot; Якщо демон негайно припиняється (наприклад, недійсна команда)status_of_proc -p $PIDFILE "$DAEMON" "$NAME" повідомте про це як про успішно запущене.

демон :
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через заплутаність параметрів командного рядка демона ; Якщо демон негайно припиняється (наприклад, недійсна команда), 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"правильно повідомте про помилку.
Мінуси : жоден.

Це переможець - найпростіше, акуратне рішення, яке, здається, працює добре.


7

Зазвичай 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

4

Цитування старого списку розсилки:

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

Простий - і якщо ви хочете використовувати демон-старт-стоп, мабуть, єдиний спосіб - це створити невеликий сценарій, що містить:

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

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

Можливо, справжнє питання полягає в тому, чи дійсно потрібно використовувати старт-стоп-демон в першу чергу?


3

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

Іншим варіантом може бути "$ DAEMON | реєстратор". logger - це команда, яка увійде в syslog (/ var / log / messages). Якщо вам також потрібен stderr, я думаю, ви можете використовувати "$ DAEMON 1> & 2 | logger"


Ви маєте рацію, використання, >>як правило, більше підходить для демонів, хоча це означає, що вам слід створити правило логротату!
joeytwiddle

Що стосується простору на диску, методи, які врізають файл, отримують простір негайно (принаймні, у файлових системах ext). Але остерігайтеся методів, які просто видаляють файл, до якого все ще записується: простір не буде повернено доти, доки ручка не буде звільнена, і ви більше не зможете знайти файловий вузол, щоб його вручну обрізати!
joeytwiddle

@joeytwiddle частина мого моменту тут полягає в тому, що є ситуації, коли logrotate не вдасться обертати журнали, якщо ручка файлу ніколи не закривається.
nairbv

--no-close ... | loggerне працює для мене (Debian 7.3, start-stop-daemon 1.16.12). Сценарій запуску-стоп-демон не повертається, хоча / var / log / повідомлення заповнені :-). Я спробував це з і без 1>&2.
hgoebl

hgoebl вам потрібно мати вираз "cmd | logger" у лапках, тому інтерпретатор буде знати, що це "cmd", який ви перекладаєте на реєстратор, а не вираз start-stop-daemon.
Wexxor

2

Якщо припустити, що це баш (хоча деякі інші оболонки також можуть це дозволити), рядок:

exec >>/tmp/myDaemon.log

надішле весь майбутній стандартний вихід у цей файл. Це тому, що execбез назви програми просто робиться якась магія перенаправлення. Із bashчоловічої сторінки:

Якщо команда не вказана, будь-які перенаправлення набувають чинності в поточній оболонці.

Управління згаданим файлом - ще одне питання.


Ви можете уточнити, де передбачається розміщувати цей рядок? Одразу після start-stop-daemonрядка, про який було сказано перше запитання?
Абдулл

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.