LiBz Tech Blog

LiBの開発者ブログ

EC2インスタンス起動時に自前スクリプトを実行するには

なにを書くのか

起動シークエンスに自前スクリプトを埋め込むときの注意について。単語的にはchkconfigcloud-init です。

なぜ書くのか

EC2インスタンス再起動時に自前スクリプトからプロセスが起動しなくてツラい思いをしたので。

結論

AWSで自前スクリプトをインスタンス起動に合わせて実行したい場合は、

  • chkconfig でサービスとして登録するならスクリプト内に start / stop を実装すること
  • cloud-init を使って登録するなら普通にスクリプトを実装すること

最初にやったこと

自前で作成したスクリプト

#!/bin/bash
# chkconfig: 2345 99 10
# description: sample script
# processname: sample

set -ex
pushd /home/sample

/usr/local/bin/docker-compose -f docker-compose.yml up -d

popd

chkconfig追加&有効化

chkconfig --add sample // 追加
chkconfig sample on // 有効化
chkconfig --list | grep sample // 登録確認

上記でサービスとして登録できたはずなのにインスタンス再起動で sample が起動に失敗(あるいはしてない?)でプロセス起動しなかった。

寄り道

ここまでchkconfig 叩くとランレベル0123456 のフラグ通りに /etc/rc.d/rc[0-6].d 以下に sample 本体へのシンボリックリンクが作成されていた。

$ ls /etc/rc.d/rc[0-6].d -al | grep sample
// ランレベル 0
lrwxrwxrwx  1 root root   25  5月 23 19:55 K10sample -> ../init.d/sample
// ランレベル 1
lrwxrwxrwx  1 root root   25  5月 23 19:55 K10sample -> ../init.d/sample
// ランレベル 2
lrwxrwxrwx  1 root root   25  5月 23 19:55 S99sample -> ../init.d/sample
// ランレベル 3
lrwxrwxrwx  1 root root   25  5月 23 19:55 S99sample -> ../init.d/sample
// ランレベル 4
lrwxrwxrwx  1 root root   25  5月 23 19:55 S99sample -> ../init.d/sample
// ランレベル 5
lrwxrwxrwx  1 root root   25  5月 23 19:55 S99sample -> ../init.d/sample
// ランレベル 6
lrwxrwxrwx  1 root root   25  5月 23 19:55 K10sample -> ../init.d/sample

上の ls の実行結果を見ると、有効化したランレベルの 2345 はサービス名 sample にプレフィックスの S99 がついていて、 無効化したランレベルの 016 はサービス名にプレフィックスで K10 が付与されていた。

再起動時の挙動としては、プレフィックス S が付与されていると サービスの start を叩きに、K の場合は stop を叩いてる模様(=細かいけど、Kでもコマンドは実行してるということ)。KS の後ろの数字は優先度が表示されてる。

ここまで書いて気づきましたが、chkconfigで追加するサービスは当然サービスなので start / stop は実装しておかないとダメなんですね。 これを怠ったので samplechkconfig から起動できなかったようです。

次にやったこと

cloud-init のサービス内で起動する。これでうまく動きました。 やったことは /var/lib/cloud/scripts/per-boot/ 以下に起動したいスクリプトを置くだけ。

つまり、start / stop が未実装の状態でサービスと登録しても当然動かないが、サービス内でスクリプトとして普通に(startを呼ばずに)実行されたので動いた。

寄り道

cloud-init も実際は chkconfig 配下で管理される1サービスだった。 /etc/rc.d/rc[0-6].d 以下を grep してみるとわかった。

$ ls /etc/rc.d/rc[0-6].d -al | grep cloud-init$
lrwxrwxrwx  1 root root   20  6月  4  2016 K50cloud-init -> ../init.d/cloud-init
lrwxrwxrwx  1 root root   20  6月  4  2016 K50cloud-init -> ../init.d/cloud-init
lrwxrwxrwx  1 root root   20  6月  4  2016 S51cloud-init -> ../init.d/cloud-init
lrwxrwxrwx  1 root root   20  6月  4  2016 S51cloud-init -> ../init.d/cloud-init
lrwxrwxrwx  1 root root   20  6月  4  2016 S51cloud-init -> ../init.d/cloud-init
lrwxrwxrwx  1 root root   20  6月  4  2016 S51cloud-init -> ../init.d/cloud-init
lrwxrwxrwx  1 root root   20  6月  4  2016 K50cloud-init -> ../init.d/cloud-init

参考

start / stop きっとこう書けばいけるはず。

case "$1" in
  start)
        hogehoge
        ;;
  stop)
        hugahuga
        ;;
  *)
        piyppiyo
esac

最後に

もし間違いあればご指摘よろしくお願いいたします。

全細胞で大喜びします。