#5
#1 では無視されてるという言及はありませんが、そこから順番に説明した方がいいですね。
まずはsleepを3秒にして、直後にechoを出力し、そのログを出力させてみます。10秒以内なので、SIGTERMで停止できず、3秒で終わりますが、SIGTERMがブロックされてるだけなら直後のecho出力がされずに終了し、SIGTERMが無視されているならecho出力が出てきます。
hoge2.sh
bash
1 # sleep.shを作成
2 cat > sleep.sh << EOF
3 sleep 3
4 echo "hoge"
5 EOF
6
7 # dockerでsleep.shをバックグラウンド実行
8 docker run -d --rm --name bash -v $( pwd ) /sleep.sh:/sleep.sh bash bash /sleep.sh
9
10 # docker logsでログ出力させる
11 docker logs -f bash &
12
13 # docker stopで停止させてみる -> 停止に3秒かかる
14 time docker stop bash
15
16 wait
bash
1 $ bash hoge2.sh
2 f546b659c7a0fd030f291bbaa1b575feaa5d44d8f7657cf3cf20e955c2468b23
3 hoge
4 bash
5
6 real 0m3.537s
7 user 0m0.031s
8 sys 0m0.004s
9 $
これで無視されていることが分かりました。念のためSIGINTでも試します。
bash
1 $ diff hoge2.sh hoge3.sh
2 14c14
3 < time docker stop bash
4 ---
5 > time docker stop -s INT bash
6 $ bash hoge3.sh
7 f16d6c814736ed5927b45a60143f1a487e92db7806963eb83fb0daae10d14557
8 hoge
9 bash
10
11 real 0m3.588s
12 user 0m0.013s
13 sys 0m0.023s
14 $
これでSIGINTでもSIGTERMでも無視されていることが分かりました。他方bashのマニュアルには以下の記述があります。
When bash is interactive, in the absence of any traps, it ignores SIGTERM (so that kill 0 does not kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin is interruptible). In all cases, bash ignores SIGQUIT. If job control is in effect, bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.
読んだ通りですが、無視されるかどうかにはiteractiveかどうかとtrapがあるかどうかが関係していることが分かります。実際どう起動されているのかは分かりませんが、少なくともtrapがあれば無視はされません。
以下はそれぞれhoge4.sh hoge5.shとし、trapを入れたものです。実際にシグナルを補足したタイミングを知るために、dateだけ入れています。
bash
1 $ diff -up hoge2.sh hoge4.sh
2 --- hoge2.sh 2023 -10-17 21 :30:55.356473047 +0900
3 +++ hoge4.sh 2023 -10-17 21 :53:13.618216200 +0900
4 @@ -1,5 +1,7 @@
5 # sleep.shを作成
6 cat > sleep.sh << EOF
7 +trap "echo trapped;date" TERM
8 +date
9 sleep 3
10 echo "hoge"
11 EOF
12 $ bash hoge4.sh
13 aab18a273ad41c1f01b25d672e1853780560abbfca0f004b72bf5e192597bdd9
14 Tue Oct 17 12 :55:43 UTC 2023
15 trapped
16 Tue Oct 17 12 :55:46 UTC 2023
17 hoge
18 bash
19
20 real 0m3.436s
21 user 0m0.023s
22 sys 0m0.014s
23 $ diff -up hoge3.sh hoge5.sh
24 --- hoge3.sh 2023 -10-17 21 :38:11.420603296 +0900
25 +++ hoge5.sh 2023 -10-17 21 :58:07.229999184 +0900
26 @@ -1,5 +1,7 @@
27 # sleep.shを作成
28 cat > sleep.sh << EOF
29 +trap "echo trapped;date" INT
30 +date
31 sleep 3
32 echo "hoge"
33 EOF
34 $ bash hoge5.sh
35 377417acce570f1b7392f427d8601d5d59a0d1ef9fd3f5fd3d0efb5dc6455476
36 Tue Oct 17 12 :58:15 UTC 2023
37 trapped
38 Tue Oct 17 12 :58:18 UTC 2023
39 hoge
40 bash
41
42 real 0m3.814s
43 user 0m0.027s
44 sys 0m0.009s
45 $
trapを入れればシグナルを補足できるのですが、sleepをブロック実行していると、シグナルを補足できるのがsleep実行後になってしまいます。そこで最後にsleep自体をバックグラウンド実行させて、シグナルを即時補足できるようにします。
bash
1 $ diff -up hoge4.sh hoge6.sh
2 --- hoge4.sh 2023 -10-17 21 :53:13.618216200 +0900
3 +++ hoge6.sh 2023 -10-18 00:11:47.341217777 +0900
4 @@ -2,7 +2,14 @@
5 cat > sleep.sh << EOF
6 trap "echo trapped;date" TERM
7 date
8 -sleep 3
9 +sleep 3 &
10 +child = \ $!
11 +wait $child # prob. trapped while waiting
12 +echo $!
13 +date
14 +wait $child # continue to wait
15 +echo $!
16 +date
17 echo "hoge"
18 EOF
19 $ bash hoge6.sh
20 9f932acb502809450fb7f46290b9eefaf069918996b132b1a49924ebf174254c
21 Tue Oct 17 15 :12:35 UTC 2023
22 trapped
23 Tue Oct 17 15 :12:35 UTC 2023
24
25 Tue Oct 17 15 :12:35 UTC 2023
26
27 Tue Oct 17 15 :12:38 UTC 2023
28 hoge
29 bash
30
31 real 0m3.736s
32 user 0m0.029s
33 sys 0m0.012s
34 $ diff -up hoge5.sh hoge7.sh
35 --- hoge5.sh 2023 -10-17 21 :58:07.229999184 +0900
36 +++ hoge7.sh 2023 -10-18 00:15:25.242971003 +0900
37 @@ -2,7 +2,14 @@
38 cat > sleep.sh << EOF
39 trap "echo trapped;date" INT
40 date
41 -sleep 3
42 +sleep 3 &
43 +child = \ $!
44 +wait $child # prob. trapped while waiting
45 +echo $!
46 +date
47 +wait $child # continue to wait
48 +echo $!
49 +date
50 echo "hoge"
51 EOF
52 $ bash hoge7.sh
53 3ee7268d05bf7bdef33fb0c467e424efca4a0315bff5820a3d732ee4e19c34c0
54 Tue Oct 17 15 :16:28 UTC 2023
55 trapped
56 Tue Oct 17 15 :16:28 UTC 2023
57
58 Tue Oct 17 15 :16:28 UTC 2023
59
60 Tue Oct 17 15 :16:31 UTC 2023
61 hoge
62 bash
63
64 real 0m3.667s
65 user 0m0.014s
66 sys 0m0.022s
67 $
trapを入れ、sleepをバックグラウンド実行することでSIGTERM/SIGINTが無視されず、ちゃんと即時補足されるようになりました。代わりにwaitが入り、その最中にSIGTERMを受けることで一旦waitが失敗(SIGTERMで異常終了)し、子プロセスを無視して終了することも、再度waitすることもできます。綺麗な終了のためには子プロセスにSIGTERM/SIGINTを送ってそれを再度waitするのが適切だと思います。それが出来ないのであれば、素直に10秒待ってSIGKILLを待つ方が潔い気がします。
ご指摘の方法では子プロセスのsleepは動作中のままコンテナごと消えてしまう運命なので、わざわざtrapする意味があまりありません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。