最新の kill コマンドの使い方まとめ（POSIX準拠）

`kill` コマンドはプロセスの停止や任意のシグナルを送るためのコマンドです。その他、プロセスの生存確認、シグナル一覧出力、シグナル名への変換機能もあります。多くのシェルではビルトインコマンドとして実装されています。（例外は おそらく posh のみ）

この記事では原則として POSIX 準拠の範囲（オプションは `-s` と `-l`）のみを解説しています。一部の実装では機能が拡張されている場合がありますが省略します。[POSIX kill の仕様はこちら](https://pubs.opengroup.org/onlinepubs/9799919799/utilities/kill.html)を参照してください。

## シグナル送信（プロセス停止）

### 推奨の書式（POSIX準拠）

シグナルを送る場合の使い方は以下のとおりです。

```console
$ kill -s シグナル名 PID
$ kill PID # kill -s TERM PID と同じ
```

シグナル名は頭に `SIG` をつけない大文字（例 `TERM`）で指定します。 POSIX では小文字のシグナル名も許容されるようですが mksh や OpenBSD ksh などで認識されません。後述しますが `0` というプロセスの生存確認を行うための特殊なシグナル名（シグナル番号も同じく `0`）も使うことができます。

PID には PID（プロセス ID）だけでなくプロセスグループ ID とジョブ ID（バックグラウンドプロセスを作成したときの ID）を指定することができます。PIDとして `0` を指定した場合は自分が属するプロセスグループ ID を指定したのと同じ意味になります。PID を `-` で始めた場合はプロセスグループ ID となり、`%` で始めた場合はジョブ ID です。

```sh
$ kill -s シグナル名 PID    # プロセス ID
$ kill -s シグナル名 -PGID  # プロセスグループ ID
$ kill -s シグナル名 %JOBID # ジョブ ID
```

### 非推奨の古い書き方（XSI拡張オプション）

シグナルの送信方法には非推奨の古い書き方があります。

```console
$ kill -シグナル名 PID
$ kill -シグナル番号 PID

例 kill -9 PID
```

POSIXでは上記の書式、および**シグナル番号による指定方法はオプションのXSI拡張機能**となっており移植性が低いということになっています。POSIX で規定されているシグナル番号（もちろんこちらもXSI拡張機能）は以下のみです。

| 番号 | シグナル名 | 番号 | シグナル名 | 番号 | シグナル名 | 番号 | シグナル名 |
| -: | - | -: | - | -: | - | -: | - |
| 0 | 0 | 1 | SIGHUP | 2 | SIGINT | 3 | SIGQUIT |
| 6 | SIGABRT | 9 | SIGKILL | 14 | SIGALRM | 15 | SIGTERM |

その他の番号も番号に対応したシグナルとして使えると思いますが、ここに挙げたシグナル番号以外は POSIX では規定されていません。また環境によってシグナル番号に対応するシグナルが異なる可能性があるので**シグナル番号ではなくシグナル名を使用しましょう**。

## プロセスの生存確認

シグナル名（およびシグナル番号）`0` は実際にはシグナルを送りませんが、プロセスの存在確認として使用することができます。`kill` コマンドはビルトインコマンドなので他の外部コマンド（`ps` コマンドなど）を使用して確認するよりも高速です。ただしシグナルを送信できる権限を持っている必要があるため、原則として自分が作成したプロセスのみを調べることができます。

```sh
# PID 1234 が存在していれば終了ステータスとして 0、存在していなければ 非 0 を返す
$ kill -0 1234 
```

## シグナルよる停止時の終了ステータス

シグナルによってプロセスが停止した場合、プロセスの終了ステータスはシグナルに応じて決まります。POSIX では決まっているのはシグナルで終了した場合の終了ステータスは 128 以上になるということだけのようです。多くのシェルではシグナル番号に 128 を加えた値が終了ステータスとなります。例えば INT シグナル（シグナル番号 2）で終了した場合の終了ステータスは 130 です。

## シグナル一覧の出力

`-l` オプションを指定するとシグナル一覧を出力します。出力形式は POSIX で `"%s%c", <signal_name>, <separator>` と規定されていますが、シェルによってフォーマットが異なるので注意する必要があります。

```sh
# bash
$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
...

# dash
$ kill -l
0 # ← 0 が含まれています
HUP
INT
QUIT
...

# ksh
$ kill -l
HUP
INT
QUIT
...

# zsh
$ kill -l
HUP INT QUIT ILL TRAP ...

# busybox 
$ busybox kill -l
 1) HUP
 2) INT
 3) QUIT
...
```

bash の出力は POSIX に準拠していませんが `set -o posix` で POSIX モードにすると zsh と同様のフォーマットになります。`<separator>` は改行またはスペースなので縦並びでも横並びでも POSIX 準拠です。シグナルの一覧に `0` を含めるかどうかは POSIX には規定されてないようです。

## シグナル名への変換

`-l` オプションの引数としてシグナル番号またはシグナルによって終了した時の終了ステータスを指定するとシグナル名へ変換することができます。

> If an exit_status operand is given and it is a value of the '?' shell special parameter (see Special Parameters and wait) corresponding to a process that was terminated by a signal, the signal_name corresponding to the signal that terminated the process shall be written. 
> 
> If an exit_status operand is given and it is the unsigned decimal integer value of a signal number, the signal_name (the symbolic constant name without the SIG prefix defined in the Base Definitions volume of POSIX.1-2017) corresponding to that signal shall be written.


```sh
$ kill -l 2
INT

$ kill -l 130
INT
```

逆にシグナル名からシグナル番号（または終了ステータス）への変換は POSIX の仕様にはありません。bash, ksh, zsh では `-l シグナル名` で出来ますが、dash, mksh, yash, posh では出来ません。もしそれが必要な場合はシグナル一覧をパースしたり `kill -l シグナル番号` から逆変換テーブルを作るとかする必要があるでしょう。

## 外部コマンド版の kill の注意点

ほとんどのシェルで`kill` はビルトインコマンドとして用意されてるので外部コマンドの `kill` を使用することはあまりないと思いますが、バグや挙動が異なる点があるので注意が必要です。まずジョブ ID が使用できません。ジョブはシェルが管理しているものなので外部コマンドからジョブ ID がわからないためです。`kill` がビルトインでない posh はもともとインタラクティブシェルとしての利用を想定しておらずジョブ制御機能自体が意図的に削除されています。

なお Debian / Ubuntu などでは procps (正確には procps-ng）、RedHat / CentOS などでは util-linux の `kill` コマンドがインストールされています。

### procps-ng 版 kill

- 終了ステータスではなくシグナル番号からシグナル名への変換しかできません。
- procps-ng 3.3.12 では `kill -l 終了ステータス` (`kill --list 終了ステータス`) の書式がバグで機能せずシグナル一覧が出力されてしまいます。期待通りに動作させるには `kill -l終了ステータス` か `kill --list=終了ステータス` の書式を使用する必要がありますが `kill -l終了ステータス` の書式は他の実装では動作しません。（このバグは procps-ng 3.3.16では修正されているようです。）
- procps-ng 3.3.16 `kill --version` でバージョン番号が取得できません。`kill from procps-ng UNKNOWN` と出力されます。

### util-linux 版 kill

- `kill -l` で出力されるシグナル一覧のリアルタイムシグナルが `RT<N> RTMIN+<N> RTMAX-<N>` のような表記になっています。