Edited at

Fabricで service sshd restart はやってはいけない

More than 3 years have passed since last update.


背景

Fabricを使って、/etc/ssh/sshd_config などを遠隔から編集し有効化する場合、編集後にサービスの再起動をしたくなるが、これはやってはいけない。たとえば次のようなコード。

def restart_sshd():

sudo("service sshd restart")

あるいは、リモートの /tmp/restart_sshd.sh に以下のコードを書いてから、それを呼び出す場合もしかり。

#!/bin/bash

service sshd restart

def restart_sshd():

sudo("/tmp/restart_sshd.sh")

上記いずれかのコードを実行してしまうと、sshd が停止した後復活してこない。そのため、SSH でアクセスすることが出来なくなる。たとえば、Amazon EC2 や Vagrant といったコンソール画面を標準で持たないサービス・ソリューションの場合、インスタンスの再起動を行わないとそのインスタンスの操作ができなくなってしまうのである。

しかし、このままでは /etc/ssh/sshd_config へ変更した設定が有効化されない。


対応策

月並みだけど、restart を使わずに reload を使えばいい。

def restart_sshd():

sudo("service sshd reload")

これで設定は有効化されるはず。

sshd をどうしても再起動しなければならない場合には、Fabric でやらずに SSH でログインしてから restart した方がよい。


追記(2015-10-23)

ここに書いてあった。

Frequently Asked Questions (FAQ) — Fabric documentation

理由は、完全に見落とし。頭になかったところ。

initスクリプト実行時に、子プロセスが上がりきる前に端末が終了し、そのまま子プロセスまで死んでしまうという理由。

今回は、sshdという、落ちたらすごくわかりやすいサービスで発生したためにすぐ把握できたが、他のinitスクリプトや似たような動作をするコマンドでも、成功しているように見えて失敗している場合もあると思うので、注意が必要。

回避する方法としては、上記公式のFAQにも有るとおり、pty=Falseを付ければいい。