他の端末でスクリプトを制御した後、Ctrl-Cを押すことはできません

他の端末でスクリプトを制御した後、Ctrl-Cを押すことはできません

私はblah.shこれを端末で実行しています。その後、別の端末で一時停止して後で再起動するスクリプトを実行していますblah.sh

...

script_id=`pidof -x blah.sh`
kill -s SIGSTOP $script_id

...

script_id=`pidof -x blah.sh`
kill -s SIGCONT $script_id

その後はバックグラウンドにプッシュされます。これを停止するには、-を入力する必要がblah.shあります。fgCtrlC

blah.sh送信後、端末の前景に自動的に表示する方法はありますかSIGCONT

ベストアンサー1

blah.sh送信後、端末の前景に自動的に表示する方法はありますかSIGCONT

まず、必要なものに応じて、必要なものを得ることSIGSTOPもできない場合もあります。


分析する

あなたの場合は、次のことが起こっていると思います。

  1. ジョブ制御は、実行しているシェルで有効になりますblah.sh。シェルは別のプロセスグループからプロセスを開始し、プロセスグループがフォアグラウンドプロセスグループであることを端末に通知します。このようにしてプロセスが前景で実行されている間、シェルは自分自身を背景にします。

  2. プロセスを実行するとkill -s STOP(他の端末に入力して)プロセスが停止し、シェルがSIGCHLD自動的に起動します。このシグナルは、「あなたの子供の少なくとも1人がブロックまたは終了しました。今、子供を確認して対応する必要がある時です。」という意味です。

  3. シェルは応答してSIGCHLD子プロセスが停止したことを確認し、自分のプロセスグループを端末のフォアグラウンドプロセスグループに設定して自分をフォアグラウンドにインポートします。送信ではなく送信する場合、SIGTSTPこれはシェルを前景にインポートする正確なメカニズムですSIGSTOP。たとえば、プロセスが実行されている端末で+を押すと、Ctrlフォアグラウンドプロセスグループが受信されます。これはシェルが反応するのではなく、プロセスを意味します。ZSIGTSTPSIGCHLD

  4. これでシェルは前景にあり、プロンプトを印刷して入力を待っています。

  5. 実行するとプロセスが続行されますkill -s CONTSIGCHLDシェルに反応させる同様のメカニズムはありません。シェルは端末の前景プロセスグループを知らず、変更しません。実際、シェルはまだ正式にフォアグラウンドにあり、プロセスはまだ正式にバックグラウンドにあります。

プロンプトを無視してシェルとの対話を中断するだけで十分だと思うかもしれません。一般的に言えば:いいえ。バックグラウンドプロセスがSIGTTIN端末(通常は標準入力)から読み取ろうとすると、メッセージが表示されます。ターミナル()の設定によっては、stty tostopバックグラウンドプロセスがターミナルSIGTTOU(ほとんどの場合stdoutとstderr)に書き込もうとすると、それを受信することもできない場合もあります。SIGTTINまたはの基本的な作業はSIGTTOUプロセスを停止することです。また、読み取りを試みている間にプロセスが停止しなくても、シェルは同じ端末で読み取られているため、シェルが入力を「盗む」ため、プロセスと対話することは困難です。

Ctrl+端末ドライバをフォアグラウンドプロセスグループにC送信できるようにします。SIGINT問題のプロセスがバックグラウンドにある場合は、信号を受信できません。

入力(他の端末から送信するfg代わりに)はシェルに組み込まれているため、実際にこれを処理するシェルであるため、うまく機能します。シェルはプロセスを前面にインポートすることを知り、独自の動作を変更します。 (端末の読み取りでプロセスを停止し)、プロセスのプロセスグループに送信する前に、それに応じてフォアグラウンドプロセスグループを設定します。SIGCONTfgfgSIGCONT

プロセスを停止した理由がシェルと対話するためのものである場合は、シェルと対話(つまりシェル呼び出し)してプロセスを再開する必要がありますfg


考えられる解決策

しかし、もしプロセスを停止した理由はシェルとは関係ありません(たとえば、プロセスがコンピューティングを停止したい場合など)。プロセスの開始方法を変更する必要があります。シェルでジョブ制御を無効にする。次のことが起こります。

  1. あなたは実行しますset +m; blah.sh set +mジョブ制御を無効にします。シェルが起動すると、blah.shプロセスはシェルのプロセスグループに配置されます。このプロセスグループは、今後も常にフォアグラウンドプロセスグループになります。

  2. プロセスを実行するとkill -s STOP(他の端末に入力して)プロセスが停止し、シェルがSIGCHLD自動的に起動します。

  3. シェルペアが反応しますSIGCHLD。子プロセスが終了したのか、ユーザーとのやり取りを再開するのかを知りたいのです。シェルは子プロセスが終了せず、停止していると報告され、ジョブ制御が無効になっているため、この場合、シェルはユーザーとの対話を再開しません。

  4. シェルとプロセスの両方がフォアグラウンドにあります。シェルは読み取りまたは書き込みを試みず、プロセスが停止します。彼らはただそこにとどまります。

  5. 実行すると、プロセスは続行されますkill -s CONT。シェルはわかりませんが、プロセスが最終的に終了するのを待ち、他に何もしないので問題ありません。


ノート

  • blah.sh技術的には、このソリューションは「端末で自動的に前景を表示する方法」ではありません。blah.sh常に前景にあるので「自動前景」する必要はありません。

  • 常に前景にあるため、blah.shその時点で停止してもCtrl+Cが送信されます。SIGTERMStoppedは受信した場合blah.shにのみ反応します。単独で送信することは子として送信することを意味せず、すぐに反応する可能性が高いです。SIGTERMSIGCONTSIGSTOPblah.shSIGSTOPCtrlC

  • SIGSTOP単独で送信することは子として送信することblah.shを意味しないため、プロセスグループ全体が常駐するプロセスグループに送信することを検討できます。何らかの理由で意図的に他のプロセスグループに含まれていない限り、各サブアイテムもそのグループに属します。 「負のPID値を使用してプロセスグループ全体を選択できます」を参照してください。SIGSTOPSIGSTOPSIGCONTblah.shman 1 kill

    通常、(シェルでジョブ制御が有効になっている場合)、その子孫はblah.shPIDと同じPGIDを持つプロセスグループにあると予想する必要がありますblah.sh。私たちのソリューションでは、(タスク制御が無効になっている場合)、その子孫がシェルと同じプロセスグループにあると予想する必要があり、blah.shPGIDはシェルのPIDと同じかもしれません。

  • set +m; blah.sh; set -mシャットダウン後にジョブ制御を自動的に再度有効にしたい場合はblah.sh有望に見えますが、Ctrl実行中に+を使用してそれを中断すると機能しません。この状況を確実に処理するためのいくつかのトラップがありますが、詳しくは説明しません。Cblah.shset -m

  • ジョブ制御が無効になると、シェルはそれを無視しますSIGTSTP。シェルによって開始されたプロセス(例えばblah.sh)もこれを無視します。 (一部のプロセスが意図的に無視されないように選択しない限り)これは、Ctrl+が機能すると期待してはいけませんZ

おすすめ記事