Предотвратите процесс убийства себя с помощью pkill

Я пишу процедуру остановки для службы запуска script:

do_stop()
{
  rm -f $PIDFILE
  pkill -f $DAEMON || return 1
  return 0
}

Проблема в том, что pkill (то же самое с killall) также совпадает с процессом, представляющим сам script, и он в основном завершает себя. Как это исправить?

Ответ 1

Вы можете явно отфильтровать текущий PID из результатов:

kill $(pgrep -f $DAEMON | grep -v ^$$\$)

Чтобы правильно использовать флаг -f, обязательно укажите весь путь к демонам, а не только подстроку. Это предотвратит убийство script (и устранит необходимость выше grep), а также из-за убийства всех других системных процессов, которые могут совместно использовать имя демона.

Ответ 2

pkill -f принимает полномасштабное регулярное выражение. Поэтому вместо pkill -f $DAEMON вы должны использовать:

pkill -f "^"$DAEMON

Чтобы убедиться, что только имя процесса начинается с данного имени демона, тогда только он убит.

Лучшим решением будет сохранение pid (Proces Id) процесса в файле при запуске процесса. И для остановки процесса просто прочитайте файл, чтобы получить идентификатор процесса, который нужно остановить/убить.

Ответ 3

Судя по вашему вопросу, вам не сложно использовать pgrep и pkill, так что вот некоторые другие варианты, которые обычно используются.

1) Используйте killproc из /etc/init.d/functions или /lib/lsb/init-functions (который когда-либо подходит для вашего дистрибутива и версии Linux). Если вы пишете службу script, вы можете включить этот файл, если в качестве примера использовали одну из других служб.

Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]

Основное преимущество использования этого заключается в том, что он отправляет SIGTERM, ждет, будет ли процесс завершен и отправит SIGKILL только при необходимости.

2) Вы также можете использовать секретный соус killproc, который должен найти идентификаторы процессов для уничтожения с помощью pidof, у которого есть опция -o для исключения конкретного процесса. Аргументом для -o может быть $$, текущий идентификатор процесса или %PPID, который является специальной переменной, которую pidof интерпретирует как вызывающий pidof script. Наконец, если демона является script, вам понадобится -x, поэтому вы пытаетесь убить script по имени, а не убить bash или python.

for pid in $(pidof -o %PPID -x progd); do
    kill -TERM $pid
done

Вы можете увидеть пример этого в статье Bash: как проверить, работает ли ваш script.