サーバーの再起動やミドルウェアの再起動を、 手作業で何度も繰り返す 必要が出てくる場面があります。 1台だけならまだしも、ミラーサーバーや複数台構成になってくると、同じ操作を台数分だけ繰り返すのは現実的ではありません。

  • 作業時間がかかる
  • 操作ミスが起きやすい
  • 精神的にも地味に消耗する

この記事が向いているのは、次のようなケースです。

  • 自分が管理している Linux サーバーで、同じ再起動作業を何度も繰り返している
  • root パスワードをスクリプトに埋め込まずに、手元の負担だけ減らしたい
  • nginx の再起動手順を、毎回同じ形で安全寄りに実行したい

逆に、第三者が管理する共有サーバーや、本番で慎重な承認フローが必要な環境では、そのまま流用せず運用ルールに合わせてください。

そこで今回は、

「リモートサーバーに接続し、root 権限で nginx を安全に再起動するまで」

という一連の流れを、できる限り自動化できないかを考えてみました。

先に結論

この方法のポイントは、危険なところだけ人が握り、定型処理だけを機械に任せる ことです。

  • SSH ログインは手動
  • su - root のパスワード入力も手動
  • nginx の停止確認、待機、再起動だけ自動

完全自動化より地味ですが、安全性と省力化のバランスが取りやすい のが利点です。

やりたいことの流れ

今回自動化したい処理は、次のようなステップです。

  1. homepage ユーザーで SSH 接続 (※ パスワード入力が必要)
  2. root ユーザーに切り替え (※ パスワード入力が必要)
  3. nginx を停止
  4. nginx プロセスが完全に終了するまで待機
  5. nginx を起動

完全な自動化を目指すなら、sshpassexpect を使ってパスワード入力まで含める方法もあります。 しかしそれらは追加ツールの導入が必要で、 パスワードをスクリプトに持たせるリスク も無視できません。

そこで今回は、

  • SSH と su のパスワード入力だけは手動
  • それ以外の処理はすべて自動

という、現実的で安全寄りな落としどころを選びました。 多少不格好ではありますが、それでも作業負荷は大幅に減らせます。

実際に作ったシェルスクリプト

以下が今回完成したスクリプトです。 SSH 接続後、su - root のパスワードを手動入力するだけで、nginx の安全な再起動まで一気に実行できます。

#!/usr/bin/env bash
set -euo pipefail

# リモートサーバーへSSH接続して、root権限で nginx を安全に再起動するスクリプト
# - 停止後、nginxプロセスが完全に終了したことを確認してから起動する
# - systemd(systemctl) 環境と SysV(service) 環境の両方に対応

HOST="xxxxxxxxxxxxx"   # 対象サーバーのホスト名(またはIP)
USER="xxxx"      # SSHログインユーザー(接続先で su により root へ昇格できること)

# -tt: 疑似TTYを強制割り当て(su のパスワード入力を手動で行うために必要)
# ここで SSH ログイン後、su のパスワード入力が求められる
ssh -tt "${USER}@${HOST}" 'su - root -c "
set -euo pipefail

# ----------------------------
# 1) nginx を停止する
#   - systemctl が使える環境では systemctl を優先
#   - そうでない場合は service コマンドで停止する
# ----------------------------
if command -v systemctl >/dev/null 2>&1; then
systemctl stop nginx
# stop後に active でなければOK(念のため失敗扱いにしない)
systemctl is-active --quiet nginx || true
else
# service 側は戻り値が不安定な環境もあるので || true で握りつぶす
service nginx stop || true
fi

# ----------------------------
# 2) nginx プロセスが完全に消えるまで待つ
#   - 最大 60 回(0.2秒×60=約12秒)チェックする
# ----------------------------
for i in \$(seq 1 60); do
# nginx がいなければ終了
pgrep -x nginx >/dev/null 2>&1 || break
sleep 0.2
done

# まだ残っていたらエラー終了(プロセス一覧も表示して原因調査しやすくする)
pgrep -x nginx >/dev/null 2>&1 && {
echo \"nginx still running\"
ps -ef | grep -E \"[n]ginx\"
exit 1
}

# ----------------------------
# 3) nginx を起動する
#   - systemctl が使える環境では systemctl を優先
#   - 起動後、active であることを確認する
# ----------------------------
if command -v systemctl >/dev/null 2>&1; then
systemctl start nginx
systemctl is-active --quiet nginx
else
service nginx start
fi

# 成功メッセージ
echo \"nginx restarted: OK\"
"'

プロセス監視の肝は、次の1行です。

pgrep -x nginx >/dev/null 2>&1 || break

pgrepプロセスが存在すれば終了コード 0、存在しなければ 1 を返します。 出力は /dev/null に捨てていますが、 終了コードだけを判定材料として使っている のがポイントです。 これにより「nginx が消えるまで待つ」という処理を、非常にシンプルに書けています。

おわりに

完全自動化ではありませんが、

  • 手作業の繰り返しを減らせる
  • ミスを防げる
  • 心理的な負担がかなり軽くなる

という点で、十分に実用的な仕組みになりました。 「全部自動にしないと意味がない」と思い込まず、 安全と効率のバランス を取るのも大事だなと感じた一件でした。

関連記事