#linux #bash #supervisord
Вопрос:
Я хочу отправлять журналы сервера боту telegram. Вот конфигурация моего руководителя:
[program:telegram-log-nginx]
process_name=%(program_name)s_%(process_num)02d
command=bash -c 'tail -f /var/log/nginx/error.log | /usr/share/telegram_log.sh nginx'
autostart=true
autorestart=true
numprocs=1
Когда я перестану руководить
supervisorctl stop telegram-log-nginx:*
процесс все еще продолжается:
ps aux | grep telegram
www-data 32151 0.0 0.0 21608 3804 ? S 20:53 0:00 /bin/bash /usr/share/telegram_log.sh nginx
Есть ли правильный способ остановить все процессы?
telegram_log.sh
#!/bin/bash
CHATID="chat"
KEY="key"
SERVICE=$1
TIME="10"
URL="https://api.telegram.org/bot$KEY/sendMessage"
while IFS= read -r line; do
read -r -d '' TEXT <<- EOM
Service: $SERVICE
$line
EOM
curl -s --max-time $TIME -d "chat_id=$CHATIDamp;disable_web_page_preview=1amp;text=$TEXT" $URL >/dev/null
done
├─supervisord,1101 /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
│ ├─php,643187 /var/www/web/artisan queue:work
│ ├─php,643188 /var/www/web/artisan queue:work
│ ├─php,643189 /var/www/web/artisan queue:work
├─systemd,640839 --user
│ └─(sd-pam),640841
├─systemd-journal,406
├─systemd-logind,1102
├─systemd-resolve,807
├─systemd-timesyn,684
│ └─{systemd-timesyn},689
├─systemd-udevd,440
├─tail,643203 -f /var/log/nginx/error.log
├─telegram_log.sh,643204 /usr/share/telegram_log.sh nginx
Комментарии:
1. Позволяет ли супервизор вам убить всю группу для процесса, как это делает systemd? Если так, то с этого я бы и начал.
2. @CharlesDuffy Я пробовал stopasgroup=правда, это не помогло
3. Интересный. Я бы очень хотел, чтобы кто-то, кто знает супервизора, зашел сюда-я довольно хорошо знаю bash и systemd по необходимости, но моя предпочтительная система инициализации-это набор daemontools; Я вообще не знаю супервизора.
4. Тем не менее… если у вас
nullglob
включена опция,telegram-log-nginx:*
оболочка может удалить ее из списка аргументов доsupervisorctl
того, как она ее увидит, сделав команду простоsupervisorctl stop
. Всегда безопаснее приводить аргументы, которые потенциально могут быть истолкованы как глобусы;supervisorctl stop 'telegram-log-nginx:*'
.5. Кстати, я бы подумал о чем-то вроде
bash -c 'exec < <(exec tail -f /var/log/nginx/error.log); exec /usr/share/telegram_log.sh nginx'
того , хотите ли вы, чтобы сигналы направлялись прямо на выполнение оболочкиtelegram_log.sh
, а не на настройку конвейера. (Это означает , что он не перейдет в копиюtail
, ноtail
выйдет, когда попытается записать в stdout и получит СИГПАЙП).
Ответ №1:
Предполагая , что у вас есть достаточно новая версия bash, которая обновляет процесс замены $!
, вы можете заставить родительский сценарий хранить идентификаторы PID обоих его прямых дочерних элементов и явно сигнализировать им во время завершения работы:
#!/usr/bin/env bash
# make our stdin come directly from tail -f; record its PID
exec < <(exec tail -f /var/log/nginx/error.log); tail_pid=$!
# start telegram_log.sh in the background inheriting our stdin; record its PID
/usr/share/telegram_log.sh nginx amp; telegram_script_pid=$!
# close our stdin to ensure that we don't keep the tail alive -- only
# telegram_log.sh should have a handle on it
exec </dev/null
# define a cleanup function that shuts down both subprocesses
cleanup() { kill "$tail_pid" "$telegram_script_pid"; }
# tell the shell to call the cleanup function when receiving a SIGTERM, or exiting
trap cleanup TERM EXIT
# wait until telegram_log.sh exits and exit with the same status
wait "$telegram_script_pid"
Это означает, что ваш конфигурационный файл может стать чем-то большим, чем:
command=bash -c 'exec < <(exec tail -f /var/log/nginx/error.log); tail_pid=$!; /usr/share/telegram_log.sh nginx amp; telegram_script_pid=$!; exec </dev/null; cleanup() { kill "$tail_pid" "$telegram_script_pid"; }; trap cleanup TERM EXIT; wait "$telegram_script_pid"'
Комментарии:
1. Попробовал ваше решение на производственном сервере, оно сработало. Спасибо!
Ответ №2:
@CharlesDuffy дал ответ
bash -c 'tail -f /var/log/nginx/error.log | /usr/share/telegram_log.sh nginx'
должно быть
bash -c 'exec < <(exec tail -f /var/log/nginx/error.log); exec /usr/share/telegram_log.sh nginx'
Комментарии:
1. Подождите, значит, предыдущее предложение сработало? Вы знаете, почему это не удалось, когда вы пробовали это раньше?