sshd再起動時にssh接続が継続する動作について
Linux/Unixサーバにsshしている際、sshdを再起動したとする。
sshdは一度終了する訳だから、現在接続しているsshも切断されるかと思いきや、接続は継続する。
今まであまり気にしていなかったけど、この振る舞いについて調べてみた。
先ず、現象の確認から
対象サーバにssh接続し、sshdを再起動してみる。
$ ssh ryozo@192.168.56.12 # 対象サーバに接続 $ hostname centos1.example.jp $ sudo service sshd restart sshd を停止中: [ OK ] sshd を起動中: [ OK ] $ hostname centos1.example.jp
sshdは一度停止されているにもかかわらず、対象サーバからは切断されていない。
プロセス構造から理由を探る
sshdプロセスの構成
先ず、sshdプロセスの構成を確認する。
この例ではサーバに対して同時に2ユーザが接続をしている状態である。
$ pstree -p #抜粋 init(1)─┬ └─sshd(2592) ├─sshd(2602) │ └─sshd(2608) │ └─bash(2609) │ └─pstree(2671) ├─sshd(2630) └─sshd(2634) └─bash(2635)
init配下にsshdのルートプロセス(2592)があり、個々のssh接続毎にsshdの子プロセス(2602と2630)が作成されている。
更にその下にsshd孫プロセスがあり、bashが起動されている。
bashにたどり着くまで、sshdルートプロセスを合わせて、3つのsshdが連なっている状態である。
再起動後のプロセス構造から分かること
ではsshdを再起動してみよう。
$ sudo sshd restart sshd を停止中: [ OK ] sshd を起動中: [ OK ] $ pstree -p #抜粋 init(1)─┬ ├─sshd(2602) │ └──sshd(2608) │ └──bash(2609) │ └──pstree(2712) ├─sshd(2630) │ └──sshd(2634) │ └──bash(2635) ├─sshd(2709)
init配下にぶら下がるsshdプロセスが3つになってる!
この結果から以下のことが分かる。
- 元々のsshdルートプロセス(2592)が消え、新たにsshdプロセス(2709)が立ち上がった
- ssh接続中のプロセス(2602、2630)は残っているが、親プロセスがinitに変わっている
つまり、再起動によって終了されたのはsshdのルートプロセス(2592)のみであり、子sshdプロセスは再起動対象外となっている。
個々のssh接続情報が保持されたプロセス(子プロセス)は生き残っているから、接続は切断されなかったのだ。
ちなみにこの状態から新たにssh接続を行うと、今回作成されたsshdルートプロセス(2709)の配下に新たにsshdのプロセスが立ち上がる。
また、生き残っていたsshd接続を切断すると、対応するinit配下のsshdが丸ごと消える。
新規の接続は再起動後のsshd(2709)が受け付け、既存の接続は、その接続が終了次第、無くなっていくのだ。
この状態でポート22をLISTENしているプロセスを調べてみると
$ sudo lsof -i:22 | egrep COMMAND¥|LISTEN COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 2709 root 3u IPv4 22206 0t0 TCP *:ssh (LISTEN) sshd 2709 root 4u IPv6 22208 0t0 TCP *:ssh (LISTEN)
となり、新規のssh接続を受け付けているプロセスは新たに立ち上がったルートプロセス(2709)であることが分かる。
もう少し突っ込んだ確認
以上の結果から、sshdのルートプロセスは新規接続の受け付けを行っていること、また、個々の接続情報はルートプロセスではなく、ssh接続毎に作られたプロセス上で保持していることが分かった。
今度はssh接続した状態で、自身の紐付くsshdルートプロセスを直接killしてみる。
$ pstree -p #抜粋 init(1)─┬ ├─sshd(2709) └──sshd(2845) └──bash(2850) └──pstree(2902) $ echo $$ 2850 $ sudo kill 2709 #sshdルートプロセスを直接kill! $ pstree -p #抜粋 init(1)─┬ ├─sshd(2845) └──bash(2850) └──pstree(3001)
ルートプロセスのみkillされ、子プロセスは生き残り、切断されなかった。
また、この状態からは、外部からのssh接続はできなかった。
なぜこのような振る舞いになるのか?
この現象はsshdの振る舞いと言うより、Linux/Unixのプロセス管理が関係している。
Linux/Unixでは親プロセスが死ぬと子プロセスは「孤児プロセス」として取り扱われる。
孤児となってしまったプロセスは即座にinitプロセスの配下に紐付けられ生き続けることができるのだ。
この動作をリペアレンティングと呼び、カーネルによって行われる。
従来、端末経由で接続し、各種コマンドを利用して作業を行う場合、親プロセスをkillした場合は子プロセスも同時に終了する動作となり、今回のsshdとは異なる振る舞いをする。
この違いはLinux/Unixのセッションやプロセスグループと呼ばれるプロセス管理の仕組みと、端末(ptsやtty)の仕様に関係している。
この辺もまた面白い話があるのだが、長くなりそうなのでまた次の機会にする。
関連記事
-
Java8のインタフェース実装から多重継承とMixinを考える
2014年3月18日、ついにJava8が正式にリリースを迎えた。 折角なので、今後、Java8の新
-
Ctrl+Cとkill -SIGINTの違いからLinuxプロセスグループを理解する
しばらくLinuxネタが続く・・。 近いうちに最近出たJava8ネタを書いてみようと思います。が、
-
「Systemd」を理解する ーシステム起動編ー
2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHEL7での変更点については、この
-
Linuxプロセス起動時の環境変数ダンプの取得
UnixやLinux上で不具合の調査等々を行う際、特定のプロセス起動時の環境変数を知りたい場合がある
-
文字コードの考え方から理解するUnicodeとUTF-8の違い
UnicodeとUTF-8の違いを理解していない方が結構居るようなので、文字コードの考え方を元に解説
-
「Systemd」を理解する ーシステム管理編ー
前回の記事「Systemd」を理解するーシステム起動編ーでは、Systemdの概念とSystemdに
-
Java8のHotSpotVMからPermanent領域が消えた理由とその影響
今回も前回の記事につづき、Java8による変更点で未だあまり紹介されていないポイントを記事にしようと
-
ipsetを使ってスマートにiptablesを設定する
ギークな知人から「vpsでiptables設定していたらルール設定数の上限に引っかかって思い通りの設
-
例示専用のIPアドレスとドメインを使いこなす
前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も引き続きネットワーク関連のネタ
Comment
Yes! Finally something about JC Huay
หวยออนไลน์
Yes! Finally something about JC Huay
mfwygf
6y108k
j8plyf
sirg5z
6sodfb
kywre2
72ggxj
3q9neg