*

sshd再起動時にssh接続が継続する動作について

公開日: : 最終更新日:2014/05/31 Linux, 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つになってる!
この結果から以下のことが分かる。

  1. 元々のsshdルートプロセス(2592)が消え、新たにsshdプロセス(2709)が立ち上がった
  2. 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)の仕様に関係している。

この辺もまた面白い話があるのだが、長くなりそうなのでまた次の機会にする。

関連記事

Ctrl+Cとkill -SIGINTの違いからLinuxプロセスグループを理解する

しばらくLinuxネタが続く・・。 近いうちに最近出たJava8ネタを書いてみようと思います。が、

記事を読む

Java8のHotSpotVMからPermanent領域が消えた理由とその影響

今回も前回の記事につづき、Java8による変更点で未だあまり紹介されていないポイントを記事にしようと

記事を読む

Linuxプロセス起動時の環境変数ダンプの取得

UnixやLinux上で不具合の調査等々を行う際、特定のプロセス起動時の環境変数を知りたい場合がある

記事を読む

Java8のインタフェース実装から多重継承とMixinを考える

2014年3月18日、ついにJava8が正式にリリースを迎えた。 折角なので、今後、Java8の新

記事を読む

「Systemd」を理解する ーシステム起動編ー

2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHEL7での変更点については、この

記事を読む

ipsetを使ってスマートにiptablesを設定する

ギークな知人から「vpsでiptables設定していたらルール設定数の上限に引っかかって思い通りの設

記事を読む

文字コードの考え方から理解するUnicodeとUTF-8の違い

UnicodeとUTF-8の違いを理解していない方が結構居るようなので、文字コードの考え方を元に解説

記事を読む

例示専用のIPアドレスとドメインを使いこなす

前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も引き続きネットワーク関連のネタ

記事を読む

「Systemd」を理解する ーシステム管理編ー

前回の記事「Systemd」を理解するーシステム起動編ーでは、Systemdの概念とSystemdに

記事を読む

Message

メールアドレスが公開されることはありません。

「Systemd」を理解する ーシステム管理編ー

前回の記事「Systemd」を理解するーシステム起動編ーでは、Syst

「Systemd」を理解する ーシステム起動編ー

2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHE

例示専用のIPアドレスとドメインを使いこなす

前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も

ipsetを使ってスマートにiptablesを設定する

ギークな知人から「vpsでiptables設定していたらルール設定数の

Java8のHotSpotVMからPermanent領域が消えた理由とその影響

今回も前回の記事につづき、Java8による変更点で未だあまり紹介されて

→もっと見る

PAGE TOP ↑