Що робить `kill -0 $ pid` у сценарії оболонки?


139

В основному, який сигнал позначає "0", тому що тут я бачу числа SIGNAL, починаючи з 1.



2
Дивіться також варіант цього питання для Unix.SE , який відрізняється від kill 0(без тире), пояснений тут і тут .
Адам Кац

Відповіді:


136

відправлення сигналу 0даному PIDпросто перевіряє, чи PIDзапущений якийсь процес із заданим , і у вас є дозвіл на надсилання сигналу на нього.

Для отримання додаткової інформації дивіться наступні вказівки:

вбити (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.
...

7
Розташування цієї інформації (якщо вона взагалі існує) сильно залежить від системи. На останніх системах на базі Debian використовуйте man 2 killзамість цього.
Тодд А. Джейкобс

2
І те, man 1 killі man 2 killінше було в моїй системі Fedora 20. Але важко помітити, поховані в обох сторінках.
slm

Або покластися на посібник із посік замість цього: If sig is 0 (the null signal), error checking is performed but no signal is actually sent. The null signal can be used to check the validity of pid. pubs.opengroup.org/onlinepubs/009695399/functions/kill.html
Томас Х'юз

2
Я відчуваю, що команда man 2 killзнаходиться за межами 1-ї поправки :)
JBaczuk

126

Це гарне запитання, оскільки ...

... важко знайти документацію на цей спеціальний сигнал. Незважаючи на те, що інші сказали, в man 1 killсистемах, що базуються на Debian, цей сигнал згадується лише :

Особливо корисні сигнали включають HUP, INT, KILL, STOP, CONT та 0.

Не особливо корисно, особливо якщо ви вже не знаєте, що робить сигнал. Він також не перерахований за результатами kill -l, тому ви не будете знати про нього, якщо ви вже не знаєте про нього.

Де знайти це документально

Про системи Debian і Ubuntu, висновок man 2 kill, частково:

Якщо sig дорівнює 0, то сигнал не надсилається, але перевірка помилок все одно виконується; це можна використовувати для перевірки наявності ідентифікатора процесу або ідентифікатора групи процесів.

Для чого це добре

Ви можете kill -0перевірити, чи працює процес. Розглянемо ці приклади.

# Kill the process if it exists and accepts signals from
# the current user.
sleep 60 &
pid=$!
kill -0 $pid && kill $pid

# Check if a PID exists. When missing, this should result
# in output similar to:
#    bash: kill: (6228) - No such process
#    Exit status: 1
kill -0 $pid; echo "Exit status: $?"

Ви також kill -0можете визначити, чи має поточний користувач права сигналізувати про певний процес. Наприклад:

# See if you have permission to signal the process. If not,
# this should result in output similar to:
#     bash: kill: (15764) - Operation not permitted
#     Exit status: 1
sudo sleep 60 &
kill -0 $!; echo "Exit status: $?"

Про mac та BSD це також задокументовано у kill(2) ось фрагменті:The kill() function sends the signal specified by sig to pid, a process or a group of processes. Typically, Sig will be one of the signals specified in sigaction(2). A value of 0, however, will cause error checking to be performed (with no signal being sent). This can be used to check the validity of pid.
lukecampbell

8
Це має бути прийнятою відповіддю. Набагато краще, ніж інші. документацію на сигнал 0 важко знайти. Це поховано на killсторінці man: "Якщо sig 0, то сигнал не надсилається, але перевірка помилок все ще виконується."
slm

6

Ця команда перевіряє, чи процес PID у $ pid живий.


1
На сторінці чоловіка написано: "Якщо sig - 0, то сигнал не надсилається, але перевірка помилок все ще виконується." Яку перевірку помилок ми тут маємо на увазі?
gjain

2
-1, оскільки процес з PID $pidможе працювати, але ви не маєте дозволу надсилати сигнал на нього.
dwalter

2
@dwalter: Якщо у вас немає дозволу, ви отримаєте EPERM. Якщо його не існує, ви отримаєте ESRCH. У kill(1)друку буде надруковано різну помилку для кожного. Таким чином, ви можете сказати, чи живе підсистема живої, незалежно від того, у вас є дозволи на надсилання сигналів чи ні. Крім того, типовим способом використання kill -0є те, щоб перевірити, чи живий підривник, навіть якщо він не завжди використовується правильно. Я б сказав, що ця відповідь правильна (крім написання).
camh

3
@camh: жодне значення повернення kill -0 $pidне буде однаковим в обох випадках. Він повернеться, 1тому ви не зможете сказати, не аналізуючи вихід, killпроцес запущений чи ні, якщо ви не маєте дозволу надсилати йому сигнал. EDIT: так, я знаю, що він використовується в більшості випадків для перевірки, чи процес живий, але це неправильно, якщо ви не зможете гарантувати, що у вас є дозвіл на надсилання сигналу (наприклад: root)
dwalter

2
@dwalter: Моя думка полягала в тому, що відповідь правильна. Ви намагалися бути педантичним і вказуєте на те, що стався ще один випадок помилки, але я кажу вам, що технічно відповідь охоплює і цей випадок, оскільки killвбудований bash (питання позначено тегом bash) видає тип помилки на stderr та вказівку помилки у зворотному коді. Тобто, "Ця команда перевіряє [чи] процес з PID в $ pid живий" є цілком правильним, якщо ви правильно інтерпретуєте вихід. [Я б не коментував, якби ти не сказав, що ти дав -1 відповіді. Ваш коментар дійсний].
camh

6

Kill -0 $ pid - це перевірити, чи існує процес з pid чи ні.

Будьте обережні, використовуючи "kill -0 $ pid", щоб перевірити існування процесу, оскільки

  1. Після виходу із запланованого процесу, його під може бути виділений іншим новоствореним процесом. (Тож не можна бути таким впевненим, що певний процес живий чи ні)

  2. У разі зомбі-процесу, для якого дитина чекає батька на дзвінок, чекайте. Тут він утримує $ pid і дає позитивний результат, поки цей процес не працює.


1

Убийте -0 $ pid, який використовується для перевірки, чи процес, який працює з $ pid, живий чи ні. Але це може бути складним, оскільки ідентифікатор процесу може бути перепризначений, як тільки процес завершиться і новий процес запуститься. Можна використовувати killall -0, щоб зрозуміти, чи працює певний процес чи ні.


0

Надсилання EXITсигналу або 0процесу буде:

  1. Перевірте наявність процесу.
  2. Робіть різні перевірки помилок у процесі (PID, PGID тощо).
  3. stdoutПісля успіху він не надсилатиме жодного результату .
  4. Надішліть повідомлення про помилку, stderrякщо щось невірно.
  5. Дайте помилковий позитив, якщо процес закінчується (тобто Zombie).

Більш чітко, корисною функцією для ваших скриптів оболонки буде:

function isProcess ()
{
    kill -s EXIT $1 2> /dev/null
}

Це не повертає текст stdoutпісля успіху, а повідомлення про помилку stderrпісля відмови (але я перенаправив це повідомлення про помилку /dev/null).

Якщо вас турбує стан неіснуючого / зомбі-процесу , тоді вам потрібно скористатися ps, бажано, --no-headersперемикачем.

#!/bin/ksh

function trim ()
{
    echo -n "$1" | tr -d [:space:]
}

function getProcessStatus ()
{
    trim $(ps -p $1 -o stat --no-headers)
}

function isZombie ()
{
    typeset processStatus=$(getProcessStatus $1)

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