`cmd1&& cmd2&& cmd3`チェーンをエレガントに一時停止して再開するには?

`cmd1&& cmd2&& cmd3`チェーンをエレガントに一時停止して再開するには?

~から前の質問&&正しく対話する方法を理解できないようです^Z

$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4
Running command3
Running command4

、チェーンが始まった後に「追加」するために使用できると思うのはcommand3最後のコマンドであり、停止するのでうまくいくようです。command2たとえば、誰が別の結果を提供します(誰がcommand3無視する必要があるか)。

&&残りのコマンドをキャンセルせずにチェーンを正常に中断する方法は?また、コマンドラインに追加のロジックが必要な場合は、終了コードを保存したいと思います。

チェーンを早く一時停止したい場合があることがわかった場合は、次のように始めることができるので、( command1 && command2 && command3 )正常に一時停止する必要があります。しかし、すぐに始めたらどうすればいいですか?

コマンドが出力を提供せず(上記の例とは異なり)、2回実行しないでください。順序が間違っている場合は、私が考えることができる唯一の方法は、を押して何が停止したかを^Z分析して手動でビルドすることです。fd && the_rest_of_commandsこれは不便で間違いが簡単です。

答え1

何が起こったのか誤解していると思います。これを行うとき:

cmd1 && cmd2

シェルはcmd1子プロセスから開始してそのプロセスを待ち、終了ステータスがcmd2ゼロの状態で終了すると起動します。cmd1

を押すとCtrl+Z待機が返され、シェルは$?148(たとえば(128 + SIGTSTP))に設定され、残りの評価は完了します。その瞬間、やはりcmd2そうです。いいえ処刑される。そしてcmd1バックグラウンド作業になります。

次のように入力する場合:

cmd1 || cmd2

または:

cmd1; cmd2

cmd2処刑される~上Ctrl-Zfgそして、次のプロンプト(またはbg可能であればバックグラウンドタスク)を受け取る前に完了するまで待つ必要があります。

でをzsh押すとCtrl-Z

{cmd1 && cmd2 && cmd3}

これにより、グループ全体が一時停止され、サブシェルに移動されます。しかし、再開時に保留中のコマンドは終了時の終了状態にかかわらず 20 に設定され、$?この問題を解決する方法がないと思うので結局同じ動作が発生します{cmd1 || cmd2}(cmd2 では) で直接実行されるのではなく cmd1 ) が完了した後に実行になりますCtrl-Z

答え2

gdb -pと一致するエレガントな一時停止を提供して、現在実行中のコンポーネントを一時停止しているようですkill -STOP

したがって、現在実行中のタスクが何であるかを知っている場合は、command2次のことができます。

gdb -p $(pgrep -f 'command2')

他の端末で一時停止し、GDBの再開を終了または再開してください。

答え3

コマンドを実行した対話型シェルである親シェルを一時停止できます。

コマンドを実行する前にPIDを印刷してください(または後でPIDを見つけてください。以下を参照)。

$ echo $$
1234

他の端末で対話型シェルを中断することで、コマンドの完全なリスト(リストは対話型シェルの子プロセスで構成されています)を停止できます。

$ kill -STOP 1234

そしてコマンドリストに進みます。

$ kill -CONT 1234


ユースケースの重要な部分であるコマンドリスト(例:)を実行する前に準備が必要ないため、リストがすでにecho $$フォアグラウンドで実行されているときに停止したいシェルのPIDを取得する方法は次のとおりです。

アイデアは、リスト内のすべてのコマンドの親プロセスPIDを見つけることです。

まず、pgrep現在実行中のコマンドのPIDを見つけるために使用します。一度に 1 つしか実行されないため、これらのうち PID を探すだけで十分です。

$ pgrep 'command1|command2|command3'

command1etcが実際にプロセスのコマンド名でない場合(たとえば、コマンドラインの最初の単語)、そのオプションを追加する必要があります-f-a実験を通してPID以上を確認するには)。

$ pgrep -f 'command1|command2|command3'

ps次にfindコマンドの親PIDを使用します。

$ ps -o ppid= 

結合すると、次のように中断するシェルのPIDを取得できます。

$ pid=$(ps -o ppid= $(pgrep 'command1|command2|command3'))

すべてを一度に:

$ kill -STOP $(ps -o ppid= $(pgrep 'command1|command2|command3'))
$ kill -CONT $(ps -o ppid= $(pgrep 'command1|command2|command3'))

関連情報