killがPIDとジョブ番号に異なる影響を与えるのはなぜですか?

killがPIDとジョブ番号に異なる影響を与えるのはなぜですか?

友達に仕事のコントロールを表示しようとしたときに予期しない動作が発生しました。一部のコマンドでは、kill はジョブ番号では機能しますが、プロセス ID では機能しません。

私が望む行動の例:

user@host:~$ sleep 1h &
[1] 4518
user@host:~$ sleep 2h &
[2] 4519
user@host:~$ kill %2
[2]+ Terminated   sleep 2h
user@host:~$ kill 4518
[1]+ Terminated   sleep 1h

どちらの場合も、睡眠は終了します。 1つはジョブ番号に基づいて、もう1つはPIDに基づいています。最初はcatコマンドを使用してこれを試しましたが、期待どおりに機能しませんでした。

user@host:~$ cat &
[1] 4521
user@host:~$ cat &
[2] 4522

[1]+ Stopped   cat
user@host:~$ kill %2
[2]+ Terminated   cat
user@host:~$ kill 4521
user@host:~$ jobs
[1]+ Stopped   cat
user@host:~$ kill 4521
user@host:~$ jobs
[1]+ Stopped   cat
user@host:~$ kill %1
[1]+ Terminated   cat

したがって、killは私のプロセスのPIDでは機能しませんが、タスク番号では機能します。私はこのようなことが起こってはいけないと思います。なぜですか?

私はDebian 9とbash 4.4.12(1)リリースを使用しています。

編集:この問題を解決しようとしたときに、catの「停止」状態が原因で基本信号SIGTERMに応答しない可能性があることに気づきました。ただし、これが本当の場合は、プロセスIDとジョブ番号でkillコマンドが失敗するはずです。そうではありませんか?

答え1

killこのような場合、組み込み関数が実際に行うことはBourne Againシェルマニュアルには文書化されていませんが、ZシェルとKornシェルマニュアルには文書化されています。

  • コーエンシェル:
    送信された信号がTERM(終了)または(中断)の場合、ジョブまたはHUPプロセスが停止するCONTと(続行)信号が送信されます。
  • Zシェル:
    送信された信号がまたKILLはでCONTないCONT場合、ジョブが停止すると信号が送信されます。

Bourne Again シェルマニュアルは次のとおりです。

送信された信号がTERMORHUPで、ターゲットプロセスがジョブの一部である場合、ジョブが停止したCONT場合、または現在の端末でジョブ制御が利用できない場合、シグナルはジョブに送信されます。

それが実際にすることだからです。

関連情報