web-dev-qa-db-ja.com

一時停止後にwhileループが停止するのはなぜですか?

Bashを使用してwhileループを一時停止すると、再開後にループが停止するのはなぜですか?以下の短い例。

$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+  Stopped                 sleep 1
$ fg
sleep 1
$

私はシグナルに精通しており、これはここでのbashの自然な動作である可能性があると思いますが、なぜこの特定の方法で動作するのかをよりよく理解したいと思います。

10
bkzland

これはいくつかのシェルのバグのように見えますが、ksh9およびzshで期待どおりに機能します。

バックグラウンド:

ほとんどのシェルは、メインシェル内でwhileループを実行しているようです。

Bourne Shellログインしていないシェルで^ Zと入力すると、シェル全体が一時停止します

bashsleepのみを一時停止し、whileループを終了して、新しいシェルプロンプトを出力します。

dashこのコマンドを一時停止不可にします

ksh9の場合、動作は大きく異なります。

ksh9コマンドが最初に開始されたときに同じことを行いますが、sleepはksh93のbuitinであるため、ksh93には、whileループがメインシェルから分岐するハンドラーがあります。 ^ Zを入力すると一時停止します。

ksh9後でfgと入力すると、ループを実行している分岐した子が続行されます。

Bashとksh93からのジョブ制御メッセージを比較すると、主な違いがわかります。

bashレポート:

[1]+ Stopped sleep 1

しかしksh9レポート:

^Z[1] + Stopped while true; do echo .; sleep 1; done

zshksh9と同様に動作します

両方のシェルで、^ Zを入力しない限り、単一のプロセス(メインシェル)と、^ Zを入力した後の2つのシェルプロセスがあります。

10
schily

私はこの問題についてBashの共著者の1人に書きました、そしてここに彼の返事があります:

これは実際にはバグではありませんが、確かに警告です。

ここでの考え方は、シェルコマンドとは異なる粒度の単位であるプロセスを一時停止することです。プロセスが一時停止されると、シェルに戻り(ゼロ以外のステータスで、たとえば、ループテストであるプロセスを停止すると結果が発生します)、ループから抜け出すか、ループを続行するかを選択できます。 、停止したプロセスを残します。 Bashは、ジョブが停止したときにループから抜け出すことを選択し、常に選択しています。ループを継続することが必要になることはめったにありません。

他のいくつかのシェルは、SIGTSTPのためにプロセスが中断されたときにシェルのコピーをフォークし、そのプロセスを停止するなどのことを行います。 Bashはこれを行ったことがありません-それは利益が保証するよりも複雑に思えます-しかし誰かがそのコードをパッチとして提出したいのであれば、私は変更を組み込むことを検討します。

したがって、パッチを送信したい場合は、manページにある電子メールアドレスを使用してください。

4
forthrin