なぜ `kill -s INT`は`Ctrl-C`とは異なる動作をしますか?

なぜ `kill -s INT`は`Ctrl-C`とは異なる動作をしますか?

次から始めましょう:

% donothing () { echo $$; sleep 1000000 }
% donothing
47139

この時点でシェルを制御する同じ端末をクリックすると、関数が終了してCtrl-Cコマンドdonothingプロンプトに戻ります。

しかし、代わりに別のシェルセッションで次を実行すると、

% kill -s INT 47139

...このdonothing機能はいいえ終了。 (-47139最後の引数として渡すと上記と同じですkill。)

kill -s INT制御端末で対話的に同じ効果を得るには、使用しているPIDとは異なるPIDを使用する必要がありますか?Ctrl-C

(私は主に答えに興味がありますzsh。)


編集:Gillesのコメントへの回答:いいえ、トラップを設定していません(トラップが設定されていないことを確認する方法を学びたい。すべてのアクティブトラップを一覧表示する方法はありますか?はい、再現できます)。この動作はzsh -f。実際、完全に「裸」の効果を得るために、私が知っている最も極端な方法でそれを再現することができます。zsh(より良い方法があれば教えてください。)

% /usr/bin/env -i /usr/bin/zsh -f
% donothing () { echo $$; sleep 1000000 }
12345

...など。

元の投稿以降、DarwinとNetBSDは上記の動作を複製しましたが、Linuxでは複製しませんでした(つまり、Linuxでは上記で定義した関数を終了しますが、kill -s INT <zsh PID>プロセスdonothingの親シェルは終了しません)。

おそらくこれはBSDスタイルです。具体的には、私が試したすべてのUnixでは、プロセスはプロセスのsleep子ですが、zshLinuxでのみプロセスSIGINTに送信された信号がプロセスに伝播されます。zshsleep

したがって、DarwinとNetBSDでこの関数を非対話式で終了させるには、donothing-ingサブプロセスのPIDを見つけてそのプロセスにsleep送信する方法が必要ですSIGINT(もちろん、これは本当に冷静に聞こえます)。より一般的には、DarwinとNetBSDで非対話式でシェル機能を終了するには、再帰的/深く優先検索を実行する必要があります。子孫処理zshして送ってくださいSIGINT...

ベストアンサー1

Control-cスリープ処理を含む端末から、端末に関連するプロセスグループに割り込み信号を送信します。 killを介してSIGINTを送信すると、1つのプロセスにのみ到達できます。この場合、$ $は休止プロセスではなくシェルのプロセスIDを返すため、無効なプロセスになります。シェルは通常 SIGINT を無視します。

おすすめ記事