`kill -0`は何をしますか?

`kill -0`は何をしますか?

最近、シェルスクリプトでこの問題が発生しました。

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

kill -0 ...効果は何ですか?

答え1

これは収集するのが少し難しいですが、次の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に何も送信しませんが、それを行う権限があることを確認します。

これはどこで役に立ちますか?

これを確認するための1つの明確な場所は、実行中のプロセスにシグナルを送信して権限があることを確認したい場合ですkillkill希望の実際の信号を送信する前に、まずチェックできるように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

これで、root以外のユーザーとして上記のコマンドを実行すると、次のようになります。

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

$ echo $?
1

ただし、rootとして実行する場合:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$

答え2

kill -0(またはより移植性の高いPOSIXバリアントkill -s 0)はシグナルを送信する操作を実行しますが、実際にシグナルを送信しません。その特徴の一つは低レベルC API考えるシェルコマンド直接的な方法で公開されます。

kill -s 0 -- "$pid"したがって、与えられたPID(または負の場合はPGID)を使用して、実行中のプロセスがあるかどうか、および$pid現在のプロセス$pidにシグナルを送信する権限があるかどうか(または負の場合はプロセスグループ内のすべてのプロセス)をテストします。主にプロセス(またはプロセスグループ)が生きているかどうかをテストする方法です。

予想されるPIDと権限を持つ実行中のプロセスがある場合でも、これが必ずしも期待したプロセスではないことに注意してください。予期したプロセスが早期に終了し、関連していないプロセスでそのPIDが再利用される可能性があります。プロセスを監視する正しい方法は、親プロセスを実行させることです。プロセスのPIDは、親プロセスが終了したことを確認するまで再利用されません。ゾンビ存在)、プロセスの親プロセスはPIDを介して子プロセスを確実に識別できます。

答え3

kill -0 $pidプロセスが存在するかどうかを示します$pid

断片的に

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

... do something ...保存されたPIDを持つプロセスが実行されている場合はブロックが実行され、/path/to/file.pidコードスニペットがrootとして実行されない限り、PIDが同じユーザーとして実行されている場合でも実行されます。

POSIX標準は、信号が実行するアクションを指定します0

sigが0(ヌル信号)の場合、エラーチェックは実行されますが、実際に信号は送信されません。ヌル信号を使用して pid を検証できます。

キル(3p), POSIX.1-2008 - POSIX.1-2001と同様の表現)

POSIXはコマンドラインkill -0スタイルkill -s 0殺す(1p))。

Killシステムコールインターフェイスと比較して、この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 システムコールが呼び出されたときの値を見ると、このような場合を明確に区別できますerrnoPythonの例)。

関連情報