次から始めましょう:
% 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
子ですが、zsh
LinuxでのみプロセスSIGINT
に送信された信号がプロセスに伝播されます。zsh
sleep
したがって、DarwinとNetBSDでこの関数を非対話式で終了させるには、donothing
-ingサブプロセスのPIDを見つけてそのプロセスにsleep
送信する方法が必要ですSIGINT
(もちろん、これは本当に冷静に聞こえます)。より一般的には、DarwinとNetBSDで非対話式でシェル機能を終了するには、再帰的/深く優先検索を実行する必要があります。子孫処理zsh
して送ってくださいSIGINT
...
ベストアンサー1
Control-cスリープ処理を含む端末から、端末に関連するプロセスグループに割り込み信号を送信します。 killを介してSIGINTを送信すると、1つのプロセスにのみ到達できます。この場合、$ $は休止プロセスではなくシェルのプロセスIDを返すため、無効なプロセスになります。シェルは通常 SIGINT を無視します。