Що робить `kill -0`?


61

Нещодавно я натрапив на це у сценарії оболонки.

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

Що робить kill -0 ...?


2
Дивіться тут, якщо ви плутаєтесь у відмінностях b / w trapкоманда Bash і 0 проти сигналу 0 від kill: Що таке сигнал 0 у команді пастки?
slm

Дивіться також старе питання StackOverflow Що робить kill -0 $pidсценарій оболонки? а також що насправді вбиває 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>спочатку було дозволено.

Приклад

Скажіть, що процес запускається під корінь наступним чином:

$ 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

Тепер, коли я запускаю вищезазначене як некореневий користувач:

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

$ echo $?
1

Однак коли він працює як root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$

9
Я також додаю, що це може бути використане для багатопроцесорних сценаріїв, щоб побачити, чи є процес все ще активним.
prateek61

1
@slm приємна знахідка. Використовуючи цю логіку зараз у сценарії, я пишу, дякую.
111 ---

12
Prateek61 має рацію. Ви не можете використовувати pgrep, розбирати psабо test -e /proc/$PIDпереносити сценарії, але kill -0працює скрізь. Якщо вам дано PID, який може бути несвіжим - наприклад, /var/runзапис - це портативний спосіб перевірити, чи процес ще живий.
Warren Young

1
Окрім того, що повідомляє, чи PID живий, він також ефективно повідомляє, чи все ще запущений процес з вашого UID, оскільки у вас немає дозволу на надсилання сигналів іншим UID (якщо ви не root). Це робить помилковими позитивні наслідки повторного використання PID менш ймовірними.
Бармар

Невдача kill -0 $(pgrep sleep)може необов'язково означати, що ти слабкий , він повернеться помилковим, якщо не sleepпрацює команда, або якщо є більше однієї і є одна, яку ти не можеш вбити, або якщо один з сну вмирає між pgrep і the kill команди, що виконуються.
Стефан Шазелас

22

kill -0(або її більш портативний варіант POSIX kill -s 0) проходить через рух відправки сигналу, але насправді не надсилає його. Це особливість основного API API, що команда оболонки відкриває прямо.

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команду не можна використовувати для надійної перевірки наявності ПІД, які належать іншим користувачам (як звичайний користувач), наприклад:

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

vs.

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

Під час виклику syscall kill можна достовірно розрізнити ці випадки, переглянувши errnoзначення (пор. Наприклад, Python Example ).

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