Как остановить процесс супервизора с помощью переданной по конвейеру команды

#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. Подождите, значит, предыдущее предложение сработало? Вы знаете, почему это не удалось, когда вы пробовали это раньше?