Нещодавно я натрапив на це у сценарії оболонки.
if ! kill -0 $(cat /path/to/file.pid); then
... do something ...
fi
Що робить kill -0 ...
?
kill -0 $pid
сценарій оболонки? а також що насправді вбиває 0? .
Нещодавно я натрапив на це у сценарії оболонки.
if ! kill -0 $(cat /path/to/file.pid); then
... do something ...
fi
Що робить kill -0 ...
?
kill -0 $pid
сценарій оболонки? а також що насправді вбиває 0? .
Відповіді:
Це трохи важко підкреслити, але якщо ви переглянете наступні 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
$
pgrep
, розбирати ps
або test -e /proc/$PID
переносити сценарії, але kill -0
працює скрізь. Якщо вам дано PID, який може бути несвіжим - наприклад, /var/run
запис - це портативний спосіб перевірити, чи процес ще живий.
kill -0 $(pgrep sleep)
може необов'язково означати, що ти слабкий , він повернеться помилковим, якщо не sleep
працює команда, або якщо є більше однієї і є одна, яку ти не можеш вбити, або якщо один з сну вмирає між pgrep і the kill команди, що виконуються.
kill -0
(або її більш портативний варіант POSIX kill -s 0
) проходить через рух відправки сигналу, але насправді не надсилає його. Це особливість основного API API, що команда оболонки відкриває прямо.
kill -s 0 -- "$pid"
таким чином перевіряється, чи існує запущений процес із заданим PID (або PGID, якщо $pid
негативний), і чи має поточний процес дозвіл на передачу (будь-який з процесів у групі процесів у разі негативного $pid
) сигналу. Це здебільшого спосіб перевірити, чи є процес (або група процесів) живим.
Майте на увазі, що навіть якщо є запущений процес із очікуваним PID та дозволами, це не обов'язково процес, який ви очікуєте. Можливо, процес, який, на вашу думку, загинув раніше, і його PID був використаний повторно для спорідненого процесу. Правильний спосіб моніторингу процесів - дозволити батькам робити це - PID процесу не використовуватиметься до тих пір, поки його батько не визнає смерть (ось чому існують зомбі ), тому батько процесу може надійно ідентифікувати своїх дітей за їх PID.
Повідомляє, 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 ).
trap
команда Bash і 0 проти сигналу 0 відkill
: Що таке сигнал 0 у команді пастки?