Что делает `kill -0`?

61

Я недавно сталкивался с этим в сценарии оболочки.

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

Что делает kill -0 ...?

SLM
источник
2
Смотрите здесь, если вы не понимаете различий между ч / б trapкомандой Бэша и 0 по сравнению с сигналом 0 из kill: Что такое сигнал 0 в команде прерывания?
СЛМ
См. Также старый вопрос StackOverflow. Что делает kill -0 $pidсценарий оболочки? а также что делает kill 0 на самом деле? ,
Адам Кац

Ответы:

76

Это немного трудно подобрать, но если вы посмотрите на следующие 2 справочные страницы, вы увидите следующие заметки:

убить (1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
убить (2)
$ man 2 kill
...
If sig is 0, then no signal is sent, but error checking is still performed; 
this can be used to check for the existence of a process ID or process 
group ID.
...

Таким образом, сигнал 0 на самом деле ничего не отправит на PID вашего процесса, но проверит, есть ли у вас разрешения для этого.

Где это может быть полезно?

Одно очевидное место было бы, если бы вы пытались определить, есть ли у вас разрешения на отправку сигналов запущенному процессу через kill. Вы можете проверить перед отправкой фактического killсигнала, который вы хотите, обернув проверку, чтобы убедиться, что это kill -0 <PID>было сначала разрешено.

пример

Скажем, процесс запускался пользователем root следующим образом:

$ sudo sleep 2500 &
[1] 15693

Теперь в другом окне, если мы запустим эту команду, мы можем подтвердить, что этот PID работает.

$ pgrep sleep
15693

Теперь давайте попробуем эту команду, чтобы увидеть, есть ли у нас доступ для отправки этих сигналов PID через kill.

$ if ! kill -0 $(pgrep sleep); then echo "You're weak!"; fi
bash: kill: (15693) - Operation not permitted
You're weak!

Так что это работает, но вывод выдаёт сообщение от killкоманды, что у нас нет прав. Ничего страшного, просто поймайте STDERR и отправьте /dev/null.

$ if ! kill -0 $(pgrep sleep) 2>/dev/null; then echo "You're weak!"; fi
You're weak!

Полный пример

Итак, мы могли бы сделать что-то вроде этого killer.bash:

#!/bin/bash

PID=$(pgrep sleep)
if ! kill -0 $PID 2>/dev/null; then 
  echo "you don't have permissions to kill PID:$PID"
  exit 1
fi

kill -9 $PID

Теперь, когда я запускаю вышеупомянутое как пользователь без полномочий root:

$ ~/killer.bash 
you don't have permissions to kill PID:15693

$ echo $?
1

Однако, когда он запускается с правами root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
SLM
источник
9
Я также добавил бы, что это можно использовать для сценариев с несколькими процессами, чтобы увидеть, является ли процесс еще живым.
prateek61
1
@Slm хорошая находка. Используя эту логику прямо сейчас в сценарии, я пишу, спасибо.
111 ---
12
Prateek61 прав. Вы не можете использовать pgrep, psанализируя или test -e /proc/$PIDв портативных записках, но kill -0работает везде. Если вы получили PID, который может быть устаревшим - например, /var/runзапись - это переносной способ проверить, все еще ли запущен процесс.
Уоррен Янг
1
В дополнение к сообщению о том, что PID активен, он также эффективно сообщает, выполняет ли он процесс с вашего UID, поскольку у вас нет разрешения на отправку сигналов на другие UID (если вы не root). Это делает ложные срабатывания из-за повторного использования PID менее вероятными.
Бармар
Провальный kill -0 $(pgrep sleep)могут не обязательно означают , что вы как раз слабые , он возвращает ложь , если нет sleepкоманды работает, или если есть более чем один и есть один , вы не можете убить, или если один из Снов умирают между pgrep и убийством команды запускаются.
Стефан Шазелас
22

kill -0(или его более переносимый вариант POSIX kill -s 0) проходит процесс отправки сигнала, но фактически не отправляет его. Это особенность лежащего в основе C API, которую команда shell предоставляет простым способом.

kill -s 0 -- "$pid"таким образом, проверяется, существует ли запущенный процесс с заданным PID (или PGID, если $pidон отрицательный), и будет ли текущий процесс иметь разрешение на отправку (любому из процессов в группе процессов в случае отрицательного $pid) сигнала. В основном это способ проверить, жив ли процесс (или группа процессов).

Имейте в виду, что даже если есть запущенный процесс с ожидаемыми PID и разрешениями, это не обязательно тот процесс, который вы ожидаете. Возможно, что ожидаемый вами процесс умер раньше, и его PID был повторно использован для несвязанного процесса. Правильный способ контролировать процессы - позволить родителю делать это - PID процесса не используется повторно до тех пор, пока его родитель не подтвердит его смерть (вот почему существуют зомби ), поэтому родительский процесс может надежно идентифицировать своих детей по их PID.

Жиль "ТАК - перестань быть злым"
источник
0

Он kill -0 $pidсообщает вам, существует ли процесс с $pid.

Во фрагменте

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

блок ... do something ...выполняется, если /path/to/file.pidзапущен процесс с сохраненным в нем идентификатором PID, и - если фрагмент не работает от имени пользователя root - если идентификатор PID выполняется под тем же пользователем.

Стандарт POSIX определяет роль 0сигнала:

Если sig равно 0 (нулевой сигнал), выполняется проверка ошибок, но сигнал фактически не отправляется. Нулевой сигнал может быть использован для проверки правильности pid.

(kill (3p), POSIX.1-2008 - аналогичная формулировка в POSIX.1-2001)

Обратите внимание, что POSIX определяет оба стиля kill -0и kill -s 0стиль командной строки (kill (1p)).

В отличие от интерфейса kill syscall, killкоманда не может использоваться для надежной проверки на наличие PID, принадлежащих другим пользователям (как обычным пользователям), например:

$ kill -0 123
kill: kill 123 failed: no such process
$ echo $?
1

против

$ kill -0 1
kill: kill 1 failed: operation not permitted
$ echo $?
1

При вызове системного вызова kill можно надежно различить эти случаи, посмотрев на errnoзначение (см., Например, пример Python ).

maxschlepzig
источник