Что делает `kill -0 $ pid` в сценарии оболочки?


140

В основном, какой сигнал представляет «0», потому что здесь я вижу числа СИГНАЛА, начинающиеся с 1.



2
См. Также вариант этого вопроса для Unix.SE , который отличается от kill 0(без тире), описанного здесь и здесь .
Адам Кац

Ответы:


138

отправка сигнала 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

Или вместо этого положитесь на руководство по posix: 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

128

Это хороший вопрос, потому что ...

... может быть трудно найти документацию по этому специальному сигналу. Несмотря на то, что говорили другие, единственное упоминание об этом сигнале в 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странице руководства : «Если sig равен 0, то сигнал не отправляется, но проверка ошибок по-прежнему выполняется».
slm

6

Эта команда проверяет, жив ли процесс с PID в $ pid.


1
На странице руководства сказано: «Если sig равен 0, то сигнал не отправляется, но проверка ошибок все равно выполняется». О какой проверке ошибок мы говорим здесь?
gjain

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

2
@dwalter: Если у вас нет разрешения, вы получите EPERM. Если его не существует, вы получите ESRCH. Для kill(1)каждого будет напечатана отдельная ошибка. Таким образом, вы можете определить, жив ли pid, независимо от того, есть ли у вас разрешения на отправку сигналов или нет. Кроме того, типичное использование kill -0- проверить, жив ли pid, даже если он не всегда используется правильно. Я бы сказал, что это правильный ответ (не считая орфографии).
camh

3
@camh: no возвращаемое значение kill -0 $pidбудет одинаковым в обоих случаях. Он вернется, 1поэтому вы не можете сказать без анализа вывода, killзапущен процесс или нет, если у вас нет разрешения на отправку ему сигнала. РЕДАКТИРОВАТЬ: да, я знаю, что большую часть времени он используется для проверки, жив ли процесс, но это неверно, если вы не можете гарантировать, что у вас есть разрешение на отправку сигнала (например, root)
dwalter

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

6

Kill -0 $ pid - проверить, существует ли процесс с pid.

Будьте осторожны при использовании kill -0 $ pid для проверки существования процесса, потому что

  1. Как только запланированный процесс завершится, его pid может быть выделен другому вновь созданному процессу. (Так что нельзя быть уверенным в том, что конкретный процесс жив или нет)

  2. В случае процесса зомби, для которого дочерний элемент ожидает вызова от родителя wait. Здесь он удерживает $ pid и дает положительный результат, пока этот процесс не запущен.


1

Убить -0 $ pid, используемый для проверки, жив ли процесс, запущенный с $ pid. Но это может быть сложно, так как идентификатор процесса можно переназначить после выхода из процесса и запуска нового процесса. Можно использовать killall -0, чтобы узнать, запущен ли конкретный процесс или нет.


0

Отправка EXITсигнала или 0процессу:

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

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

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.