GNU/Linux >> Linux の 問題 >  >> Linux

バックグラウンド プロセスは、ログオフ時に SIGHUP を取得しますか?

解決策 1:

答えが見つかりました。

BASH の場合、これは huponexit に依存します。 組み込みの shopt を使用して表示および/または設定できる shell オプション コマンド。

少なくとも RedHat ベースのシステムでは、このオプションはデフォルトでオフになっているようです。

詳細については、BASH の man ページを参照してください:

<ブロック引用>

デフォルトでは、シェルは SIGHUP を受け取ると終了します。終了する前に、対話型シェルは、実行中または停止中のすべてのジョブに SIGHUP を再送信します。停止したジョブには SIGCONT が送信され、SIGHUP を確実に受信できるようになります。シェルが特定のジョブにシグナルを送信しないようにするには、ジョブ テーブルから disown ビルトイン (以下のシェルの組み込みコマンドを参照) を使用して削除するか、disown -h を使用して SIGHUP を受信しないようにマークする必要があります。

huponexit シェル オプションが shopt で設定されている場合、対話型ログイン シェルが終了すると、bash はすべてのジョブに SIGHUP を送信します。

解決策 2:

テストでは SIGHUP で送信されます:

シェル1:

[[email protected]: ~] ssh localhost
[[email protected]: ~] perl -e sleep & 
[1] 1121
[[email protected]: ~] ps
  PID TTY          TIME CMD
 1034 pts/46   00:00:00 zsh
 1121 pts/46   00:00:00 perl
 1123 pts/46   00:00:00 ps

シェル 2:

strace -e trace=signal -p1121

Shell1 再び:

[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

再びシェル 2 :

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

まだ実行されているのはなぜですか?:
これについては、Stevens による Unix 環境での高度なプログラミング セクション 9.10:Orphaned Process Groups で説明しています。最も関連性の高いセクションは次のとおりです:

<ブロック引用>

親プロセスが終了するとプロセス グループは孤立するため、POSIX.1 では、新たに孤立したプロセス グループ内の (子プロセスのように) 停止されたすべてのプロセスに、ハングアップ シグナル (SIGHUP) に続いて続行シグナル (SIGCONT) を送信する必要があります。

これにより、ハングアップ シグナルを処理した後、子プロセスが続行されます。ハングアップ シグナルのデフォルトのアクションは、プロセスを終了することです。したがって、sig_hup 関数の printf が pr_ids 関数の printf の前に現れることが期待されます。

解決策 3:

CentOS 7.1 と bash を使用していくつかのテストを実行しました。これは huponexit を意味することに注意してください off です デフォルトでは、私のテストの大部分ではオフでした.

nohup が必要です ターミナルでジョブを開始したとき。シェルを正常に終了せずにターミナルを閉じた場合端末 bash SIGHUP シグナルをシェルに送信し、シェルはそれをすべての子に送信します。シェルを正常に終了する場合 - つまり、ジョブは既にバックグラウンドにある必要があるため、 exit と入力できます または、コマンド プロンプトで Control-D を押します。bash からバックグラウンド ジョブに送信されるシグナルは一切ありません。

テスト:

ターミナル 1

$ echo $$
16779

ターミナル 2

$ strace -e signal -p16779
Process 16779 attached

(ターミナル 1 を閉じ、ターミナル 2 に表示):

--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16777, si_uid=3000090} ---
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f7ace3d9a00}, {0x456880, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], SA_RESTORER, 0x7f7ace3d9a00}, 8) = 0
kill(16779, SIGHUP)                     = 0
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16779, si_uid=3000090} ---
+++ killed by SIGHUP +++

ジョブ doit.sh :

#!/bin/bash

imhupped() {
        echo "HUP" >> /tmp/outfile
}

trap imhupped SIGHUP

for i in $(seq 1 6); do echo out $i >> /tmp/outfile; sleep 5; done

ターミナル 1 のバックグラウンドで起動します:

ターミナル 1

$ ./doit.sh &
[1] 22954

ターミナル 2 でそれを追跡します。数回ループした後、ターミナル 1 を閉じます:

ターミナル 2

$ strace -e signal -p22954
Process 22954 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22980, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7a5d547a00}, {0x43e4b0, [], SA_RESTORER, 0x7f7a5d547a00}, 8) = 0
...
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=21685, si_uid=3000090} ---
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=23017, si_status=SIGHUP, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
...

ターミナル 3 での出力:

ターミナル 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

ただし、 bash を終了すると 、子にシグナルをまったく送信せずに単に終了します。子シェルがなくなったので端末は終了しますが、子シェルが既になくなっているため、もちろん HUP する人はいません。 SIGINTSIG_BLOCKSIG_SETMASK 以下に表示されているのは sleep によるものです

ターミナル 1

$ ./doit.sh &
26275

ターミナル 2

$ strace -e signal -p26275
Process 26275 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26280, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0


(..."exit" is typed in bash, notice no new signals sent...)


rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26303, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0

ターミナル 3、出口

out 1
out 2
out 3
out 4
out 5
out 6

興味深いことに、私は huponexit を設定しました shopt -s huponexit; shopt を続ける (後者は確認する必要があります)、最後のテストを実行し、再び bash がバックグラウンド プロセスにシグナルを送信しませんでした .さらに興味深いことに、bash で見たように 閉じた端末から信号を受信した後、バックグラウンドプロセスに信号を送信します。 huponexit のようです どちらにしても関係がありませんでした.

これにより、HUP シグナルがいつ、どのように送信されるかについて、少なくとも bash の幸せに関する謎や混乱が解消されることを願っています。少なくとも、私のテストは完全に再現可能でした。 bash の動作に影響を与えている可能性のある設定が他にあるかどうか知りたいです。

そして、いつものように、YSMV (Your Shell May Vary)

補遺 1

exec /bin/sh としてシェルを実行すると 、次にスクリプトを /bin/sh ./doit.sh & として実行します 、その後、シェルを正常に終了します。バックグラウンド ジョブにシグナルは送信されず、完了まで実行され続けます。

補遺 2

exec /bin/csh としてシェルを実行すると 、次にスクリプトを /bin/sh ./doit.sh & として実行します 、その後、シェルを正常に終了します。バックグラウンド ジョブにシグナルは送信されず、完了まで実行され続けます。


Linux
  1. cPanel にアクセスすると 404 エラーが発生する

  2. コマンドが長くなりすぎると、コマンドライン自体が上書きされます

  3. linux-vserver があるのになぜ LXC なのですか?

  1. バックグラウンドプロセスの出力を確認できるのはなぜですか?

  2. nice プロセスを除いた負荷平均を取得する

  3. TCP SACK をオフにするタイミング

  1. 18.04でYoutube-dlを更新しようとするとエラーが発生しますか?

  2. バックグラウンドプロセスのプロセスIDを取得するには?

  3. zshですべてのバックグラウンドプロセスを強制終了するには?