Amazon Linux 2 が起動してネットワークが有効になった後で自作スクリプトを実行する方法を調べてみた

Amazon Linux 2 への移行はお済みでしょうか?起動時にスクリプトを実行する場合にどうするべきなのかとお悩みでしたら是非ご一読ください。
2020.06.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんばんは、菅野です。
Amazon Linux を使っていた頃は、起動時にスクリプトを実行する場合に以下のどちらかを使っていたと思います。

  • rc.local に記述する
  • initd を利用する

今回のブログでは「Amazon Linux 2 として正しいお作法」を調べてみました。
条件としては「ネットワークが有効になった後」に実行されること、となります。

正しいお作法としては systemd を使う

Amazon Linux 2 では「systemd」を使いましょう。
実行したいスクリプトの他に一つのファイルを用意するだけで簡単に目的は達成できます。

用意するファイル

自作スクリプト

  • ファイル名:/home/ec2-user/exec_ping.sh
  • Owner:ec2-user
  • パーミッション:755
  • 説明:yahoo へ ping を撃ち、その結果を result.txt へ記録します
    • 一つ目の引数でどこから起動されたかを、二つ目で start か stop を受け取るようにしています
#!/bin/bash

rc=0

case "$2" in
start)
  /usr/bin/echo >> /home/ec2-user/result.txt
  /usr/bin/echo $1 >> /home/ec2-user/result.txt
  /usr/bin/ping -c 1 www.yahoo.co.jp | grep "bytes from" >> /home/ec2-user/result.txt
  [ $? -ne 0 ] && rc=1
  ;;
stop)
  ;;
esac

exit $rc

systemd のユニットファイル

  • ファイル名:/etc/systemd/system/test.service
  • Owner:root
  • パーミッション:644
  • 説明:ネットワーク起動後に /home/ec2-user/exec_ping.sh を実行します
[Unit]
Description=exec by systemd
After=network-online.target

[Service]
Restart=no
Type=simple
RemainAfterExit=yes
ExecStart=/home/ec2-user/exec_ping.sh systemd start
ExecStop=/home/ec2-user/exec_ping.sh systemd stop

[Install]
WantedBy=network-online.target

自動起動の設定

ファイルを用意しただけではインスタンス起動時に「exec_ping.sh」は実行されません。
以下のコマンドを実行して自動起動されるように登録しましょう。

$ systemctl daemon-reload
$ systemctl enable test

以下のコマンドで登録されたのかを確認します。

$ systemctl list-unit-files | grep test

うまく動いたか再起動後に確認

結果は「/home/eco-user/result.txt」に追記されてますので確認します。

systemd
64 bytes from 182.22.28.252 (182.22.28.252): icmp_seq=1 ttl=43 time=3.83 ms

systemd が実行した ping の結果が返ってきました。

結果

先ほど記載した systemd のユニットファイルを用意すれば、Amazon Linux 2 でネットワークが有効になった後に任意のスクリプトを実行することが可能です。

ここからは余談

今までの内容で、このページにたどり着いた皆さんの目的は達成されたかと思います。
ここから先は目的を達成された方には無関係な内容となりますが、見ても損しませんので引き続きどうぞ。

今までの方法は使える?

試してみましょう。 ということでいくつかのファイルを用意します。

rc.local 検証用ファイル

  • ファイル名:/etc/rc.d/rc.local(既存ファイル)
  • Owner:変更しない
  • パーミッション:755(sudo chmod +x /etc/rc.d/rc.local を実行して変更)
  • 説明:ファイルは存在しますので、以下の1行を追記します
/home/ec2-user/exec_ping.sh rclocal start

initd 検証用ファイル

  • ファイル名:/etc/rc.d/init.d/init01(他に末尾10〜90、99も用意)
  • Owner:root
  • パーミッション:755
  • 説明:ファイル内に「chkconfig」と書かれている部分の2番目の数字を変更して異なる実行優先度を指定する
    • 書き換えるのは「chkconfig」の行とスクリプトを実行する行の1番目の引数(init10では「initd_10」とする)
#! /bin/bash
#
# test01       exec ping at 1
#
# chkconfig: 2345 1 90
# description: exec /home/ec2-user/exec_ping.sh
#

# Source function library.
. /etc/init.d/functions

/home/ec2-user/exec_ping.sh initd_01 $1

再起動して結果を確認

再起動後に「/home/ec2-user/result.txt」を確認してみると以下のようになっていました。

initd_01

initd_10

rclocal
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.15 ms

systemd
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.20 ms

initd_20
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.10 ms

initd_30
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.22 ms

initd_40
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.19 ms

initd_50
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.07 ms

initd_60
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.11 ms

initd_70
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.10 ms

initd_80
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.20 ms

initd_90
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.21 ms

initd_99
64 bytes from 183.79.219.252 (183.79.219.252): icmp_seq=1 ttl=42 time=8.12 ms

余談の結果

  • 今までの方法は、現時点の Amazon Linux 2 でも引き続き使える
  • ネットワークは優先度10で実行されている
    • /etc/rc.d/init.d/network で優先度が10となっていたので、この設定が利用されている様子
  • init01と init10 は ping の応答が返ってきていない
    • ネットワークが有効になっていないタイミングで実行された
    • 同じ優先度なのに「network」より先に実行されたのはアルファベット順のため
  • rc.local はネットワーク起動後に実行される
  • systemd でネットワーク起動後を指定して実行するよりも rc.local の方が先に実行される

最後に

いかがでしたでしょうか。
起動時に実行する自作スクリプトは、ネットワークの準備ができた後で自動実行されることが望ましいことがほとんどかと思われます。
今回記述した systemd のユニットファイルが皆さんのお役に立てれば幸いです。

参考ページ

以下のページを参考にさせていただきました。
ありがとうございました。