screen
でアプリケーションを実行し、screen
が終了してもアプリケーションを実行し続ける必要があるとします。次のコマンドは、「sleep 1
」が追加されている場合にのみ機能します。 「sleep 1
」がないと機能しないのはなぜですか?
screen -d -m -L sh -c 'DISPLAY=:0 Nohup zenity --info --text test >/dev/null 2>/dev/null &'
これはタイミングの問題のようです。Nohup
には、親の1つからシグナルが送信される前に、シグナルを無効にするのに十分な時間がありません。これは、screen
コマンドの前にstrace -o /tmp/s -ff
を追加してから、ログファイルの1つ/tmp/s.*
に追加することで確認できます。
...
access("/bin/Nohup", X_OK) = 0
stat("/bin/Nohup", {st_mode=S_IFREG|0755, st_size=36696, ...}) = 0
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---
+++ killed by SIGHUP +++
起動を簡素化できます。これは、&
を必要とせずに機能します。
DISPLAY=:0 screen -d -m -L Nohup zenity --info --text test
別の解決策は、親シェルにジョブ制御を使用するように依頼することのようです。これにより、バックグラウンドでSIGHUPが無効になるか、子Nohup
がさらにオンになるのを待ってから終了するようです。元のコマンドでsh -cm
の代わりにsh -c
を使用するとうまくいくはずです。たとえば、これは私のために働きます
screen -d -m -L sh -cm 'Nohup zenity --info --text test >&/dev/null & echo'
一方、-c
versonはそうではありません。 bash
にはdisown
コマンドがあり、ジョブ制御を使用している場合、バックグラウンドジョブをSIGHUPから保護しますが、これも機能するため、Nohup
がなくても必要ないようです。 screen
プロセスを実行したままにしないで:
screen -d -m -L sh -cm 'zenity --info --text test >&/dev/null </dev/null & echo'
Nohup
をすべてを含むコマンドとして使用することは不可能です。すべての出力を抑制せずにNohup.out
を削除することはできず、Nohup.out
の代わりにscreenlog.0
を使用することは不可能です。 Nohup.out
はキャリッジリターンを保持しないためです。
Nohup
を使用する代わりに、シェルのtrap
を使用します。したがって、OPのコマンドは次のようになります。
screen -d -m -L sh -c 'trap "" HUP; DISPLAY=:0 zenity --info --text test >/dev/null 2>/dev/null &'