この問題これは別の関連する質問にインスピレーションを与えました。始めると想像してください
% nohup a.sh &
その後、完了時に実行されますb.sh
(例:処理される出力。どちらも完了するのに数時間かかる長期実行プロセスです)。a.sh
b.sh
a.sh
a.sh
b.sh
基本的にシミュレーションしたい
% nohup a.sh && b.sh
b.sh
しかし、起動時に追加するのを忘れましたa.sh
。これは達成できますか?好ましくはzshで。
答え1
プロセスを開始したシェルがまだそれを認識している場合(これを実行しようとするとjobs
)、組み込みシェルはwait
プロセスが完了するのを待つことができます。次のように動作します。
$ jobs
[1] nohup a.sh
$ wait -f %1 && nohup b.sh &
シェルから切断された場合、pidwait
コマンドは同様の方法で動作できます。ただし、最初のプロセスの終了値を取得できず、最初のプロセスが失敗しても、2番目のプロセスを実行できます。これはdoneとは一致しません&&
。
答え2
親プロセス(または親プロセスがあるinit
場合、または終了した場合は子収穫機)のみがプロセスの終了ステータスを取得できます。
コマンドを実行したシェルでコマンドを待って成功すると、バックb.sh
グラウンドで起動できます。a.sh
wait $pid && nohup b.sh &
zshからまたは:
wait -f "$pid" && { nohup b.sh & }
最新バージョンのbashでは、(プロセスが単に停止すると-f
forは返されません。これはbashのデフォルト動作です)。wait
zsh
ただし、wait
フォアグラウンドで実行する必要があります。バックグラウンドで実行されている場合はサブシェルプロセスにあるため、実行中のプロセスの親プロセスではありませんnohup a.sh
。
自分ではない子プロセスの終了状態を取得する 1 つの方法は、デバッガとインターセプト_exit()
またはexit_group()
同等のシステムコールを使用することです。
たとえば、Linuxでは、次のようにできます。
ret=$(strace -qqqa0 -e signal=none -e exit_group -p "$pid" 2>&1 | grep -Po '\(\K\d+')
macosに対応するコマンドにはtruss
ordtrace
コマンドを含めることができますが、テストするシステムはありません。