[bash]シェルからログアウト時にSIGHUP送信する

bash では huponexit を ON にすると、シェルからログアウトした時に、ログインシェルの各ジョブにシグナル SIGHUP を送信することができる。
手元の Ubuntu 12.04 だと、デフォルトは OFF

オプション操作

オプションの一覧表示

shopt で一覧が表示される

$ shopt | grep huponexit
huponexit       off

オプションの切り替え

コマンド shopt-s/u オプションがそれぞれ on/off に対応する。
s/u は set/unset のことらしい。

$ shopt -s huponexit; shopt | grep huponexit
huponexit       on
$ shopt -u huponexit; shopt | grep huponexit
huponexit       off

Bash Manual : 4.3.2 The Shopt Builtin
http://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html

huponexit が on になっているセッションでは、シェルログアウト時に各ジョブに対して SIGHUP が送信される。

特定のジョブだけ SIGHUP シグナル送信を無効化したい

方法としては

  1. プロセスをジョブから外す
  2. 特定のジョブには SIGHUP シグナルを送信しない

の2通りがある。何れのケースでも disown コマンドを利用する。

プロセスをジョブから外す

ジョブテーブルから外したいジョブ番号を disown コマンドの引数に指定する。

$ disown %1

特定のジョブには SIGHUP シグナルを送信しない

SIGHUP を受けとりたくないジョブ番号を disown コマンドの -h オプションに続けて引数に指定する。
この場合、対象ジョブはジョブテーブルには残ったままになる。

$ disown -h %1

Bash Manual : 3.7.6 Signals
https://www.gnu.org/software/bash/manual/html_node/Signals.html

実行例

バックグラウンドでプロセスを3つ走らせ

  • 通常
  • SIGHUP だけ除外
  • ジョブテーブルから除外

の3パターンを用意し、ログアウトして各プロセスが受け取るシグナルを確認。

バックグラウンドプロセスを作成

$ sleep 300 &
[1] 9804
$ sleep 300 &
[2] 9805
$ sleep 300 &
[3] 9806
$ jobs
[1]   Running                 sleep 300 &
[2]-  Running                 sleep 300 &
[3]+  Running                 sleep 300 &

$ pstree -a -p
init,1
...
  ├─sshd,703 -D
  │   └─sshd,9534
  │       └─sshd,9720
  │           └─bash,9721
  │               ├─pstree,9816 -a -p
  │               ├─sleep,9804 300
  │               ├─sleep,9805 300
  │               └─sleep,9806 300

bash プロセス から 3つのコマンドが spawn されている。

disown コマンド実行

作成した3つのプロセスに対して

  • ジョブ番号1はジョブテーブルから除外
  • ジョブ番号2はSIGHUP だけ除外
$ jobs
[1]   Running                 sleep 300 &
[2]-  Running                 sleep 300 &
[3]+  Running                 sleep 300 &
$ disown %1
$ disown -h %2
$ jobs
[2]-  Running                 sleep 300 &
[3]+  Running                 sleep 300 &

jobs コマンドを実行すると、ジョブ番号1 は一覧から消えている。

signal を strace

別ターミナルを開き、作成した3つのプロセスに対して strace でアタッチし、システムコール signal を監視する。
sleep を実行したシェルからログアウトすると disown しなかったジョブ番号#3(pid:9806)には SIGHUP が送信され、 disown した残り2つのプロセスには SIGNUP が送信されない。

$ sudo strace -e trace=signal -p 9804 -p 9805 -p 9806
Process 9804 attached - interrupt to quit
Process 9805 attached - interrupt to quit
Process 9806 attached - interrupt to quit
[pid  9806] --- SIGHUP (Hangup) @ 0 (0) ---
Process 9806 detached
Process 9804 detached
Process 9805 detached

pid:9804, 9805 はログアウト後は親プロセスがいなくなるので(orphan)、init プロセスにぶら下がる

$ pstree -a -p
init,1
...
├─sleep,9804 300
├─sleep,9805 300

メモ

「プロセスに & をつけてバックグラウンド実行しログアウトすると、 SIGHUP シグナルを受けてプロセスが終了する、、、」というのような記述を見かけたので、ちょっと調査した。
bash の場合は huponexit オプションが有効になっていない限りは、そのようなことはないはず。

Leave a comment