さくらのクラウド スタートアップスクリプトでのベストプラクティス(motdで通知編)


先日さくらのクラウドにLet's encryptスタートアップスクリプトが追加されました。

さくらのクラウド スタートアップスクリプト「Let's Encrypt」の提供開始のお知らせ

このスクリプトの内容を眺めていたところ、ユーザーへの通知についてmotdを使ってうまく処理していました。
スタートアップスクリプトを作る上でベストプラクティスといっても良いうまいやり方だったのでここにまとめておきます。

さくらのクラウドでのスタートアップスクリプトとは?

さくらのクラウドではスタートアップスクリプトと呼ばれる、サーバ起動時に実行させたいスクリプトを登録する仕組みが用意されています。

スタートアップスクリプトの動作の詳細は以下のドキュメントにまとめられています。

さくらのクラウド マニュアル: スタートアップスクリプトとは

大まかな流れは以下の通りです。

  • 実行したいスクリプトをあらかじめさくらのクラウドのコントロールパネルから登録しておく
  • サーバ作成時に登録していたスタートアップスクリプトを実行するように指定する
  • 指定したスクリプトは/etc/rc.local経由で起動される
  • ログは/root/.sacloud-api/notes/スタートアップスクリプトID.logに出力されている
  • 実行完了すると/root/.sacloud-api/notes/スタートアップスクリプトID.doneファイルが作成される

問題:スクリプトが実行中なのか調べるのが面倒

スクリプトの処理がすぐに終わるものであれば問題ないのですが、中には実行に長時間必要なスクリプトもあります。
サーバの作成が完了しSSH接続できる段階になっても裏でスクリプトが実行中ということもあります。

実行完了を知る仕組みとしてスクリプトの処理が終わったらメールを飛ばすといった方法もあるのですが、いちいちスクリプトにメール送信処理を組み込むのも面倒です。

もちろんスクリプトの実行ログを参照すれば良いのですが、ログがちょっとわかりにくい場所にあるため、慣れている人でないとログの場所がわからないということもありました。

解決方法: motdを使ってログイン時に通知する

それを解決してくれるのが今回紹介するmotdを用いる方法です。

motdとは

motdとはMessage Of The Dayの略で、/etc/motdファイルに記載された内容をログイン後に表示してくれるという仕組みです。
(なお、/etc/issueというログイン前に通知してくれる仕組みもあります)

スタートアップスクリプト実行開始時に/etc/motdに処理中である旨を記載しておき、処理が完了したら削除するという形にすれば、SSH接続時点でまだ処理中であるか知ることができます。

Let's encryptスタートアップスクリプトでのmotd処理方法

Let's encryptスタートアップスクリプトでは以下のような関数でmotdの処理を行っています。

_motd() {
 LOG=$(ls /root/.sacloud-api/notes/*log)
 case $1 in
  start)
   echo -e "\n#-- Startup-script is \\033[0;32mrunning\\033[0;39m. --#\n\nPlease check the log file: ${LOG}\n" > /etc/motd
  ;;
  fail)
   echo -e "\n#-- Startup-script \\033[0;31mfailed\\033[0;39m. --#\n\nPlease check the log file: ${LOG}\n" > /etc/motd
   exit 1
  ;;
  end)
   cp -f /dev/null /etc/motd
  ;;
 esac
}

_motd関数にstart/fail/endのいづれかを引数で指定することで処理を切り替えていますね。
処理内容としては単純に/etc/motdにメッセージを書き込む or /etc/motdを空にするとなっています。

echoでゴチャゴチャして見えるのは色つけのためのエスケープシーケンスです。

あとはこれをスクリプトの各所から呼び出すだけでOKです。

# 開始時
_motd start

# エラー発生時
_motd fail

# 終了時
_motd end

実行例(実行中)

実行例(失敗時)

まとめ

motdをうまく使えばスタートアップスクリプトの実行中の通知を手軽に処理できますね。
SSHで接続できているし一見うまくいってそう、、だけど実はスタートアップスクリプトを実行中だったという状況は結構頻繁に見かけるので、この方法を用いればその辺りシンプルに解決できそうです。

非常に短いスクリプト(関数)で対応できるので是非スタートアップスクリプト作成の際はこの方法を組み込んでみてはいかがでしょうか?

以上です。