おれさまラボ

実際に手を動かして理解を深めるブログ。

AWS EC2 インスタンス起動時にユーザーデータを指定して設定を自動化する方法

はじめに

前回の記事で、プロンプトの設定を検証しました。

www.oresamalabo.net

自分の場合は、建てたサーバーでいつもこのプロンプトで表示してほしいので自動化したいと思いました。

AWS EC2 インスタンス起動時にはユーザーデータを指定して yum のようなコマンドを使ったインストールや設定変更を自動化できます。簡単じゃん、と思ったのですが、案外はまったのでメモとして残しておきます。

設定方法

例によって Amazon Linux 2 環境で設定しています。

自分は最終的に SSM エージェントのインストールやタイムゾーンロケールの設定も含めて以下のようなシェルスクリプトにまとめました。

#!/bin/bash
sudo yum update -y
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
sudo yum install -y git
sudo echo '#!/bin/bash' | sudo tee -a /etc/profile.d/prompt.sh
sudo echo '# custom profile ssettings' | sudo tee -a /etc/profile.d/prompt.sh
sudo echo 'export PS1="[\D{%H:%M:%S %Z}] \u@\h: \w\n\$ "' | sudo tee -a /etc/profile.d/prompt.sh
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
sudo cat /etc/sysconfig/clock | sed -e '0,/UTC/ s/UTC/Asia\/Tokyo/'

これでプロンプトが以下のように表示されます。

[18:28:16 JST] ssm-user@ip-10-255-1-179: /usr/bin
$

ハマりどころ①:.bashrc

自分の環境では SSM のセッションマネージャを使ってインスタンスに接続するようにしているので、ssm-user の .bashrc に設定を書き込もうとしました。これがうまくいきません。

EC2 起動時に指定したユーザーデータは cloud-init と呼ばれるプロセスによって実行され、その実行ログは /var/log/cloud-init-output.log に吐き出されます。

$ tail /var/log/cloud-init-output.log

Complete!
Cloning into 'my-configurations'...
chown: invalid user: 'ssm-user:ssm-user'
cp: cannot create regular file '/home/ssm-user/.bashrc': No such file or directory
May 24 08:10:11 cloud-init[3379]: util.py[WARNING]: Failed running /var/lib/cloud/instance/scripts/part-001 [1]
May 24 08:10:11 cloud-init[3379]: cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)
May 24 08:10:11 cloud-init[3379]: util.py[WARNING]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python2.7/site-packages/cloudinit/config/cc_scripts_user.pyc'>) failed
ci-info: no authorized ssh keys fingerprints found for user ec2-user.
Cloud-init v. 19.3-2.amzn2 finished at Sun, 24 May 2020 08:10:12 +0000. Datasource DataSourceEc2.  Up 50.21 seconds

どうも ssm-user がこの時点では存在していないようです。もしかしたら、セッションマネージャで接続しに行くまで ssm-user はつくられないのかもしれません。

解決方針としては、全ユーザーが読み込む設定を変更しようと思いました。

ハマりどころ②:全ユーザー用の環境設定ファイルはどこ?

以下のサイトを参考に /etc/profile に設定しようと思いましたがうまくいきませんでした。

参考:ユーザーの環境変数を設定するbashの設定ファイルと、カスタムプロンプトについて | OXY NOTES

以下のサイトによると、/etc/profile.d/prompt.sh というファイルをつくることで、全ユーザーで同じ設定が読み込まれるそうです。

参考:[Sy] EC2インスタンスを再起動せずに Amazon Linux のプロンプトにニックネームを設定する方法 | Syntax Error.

シェル起動時にどのような順番でファイルが読み込まれるのかは、以下図が参考になります。

参考:Shell startup scripts — flowblok’s blog

ハマりどころ③:ファイルへの追記

sudo でファイルの追記を行うのが意外と難しかったです。いくつか方法がありますが、今回はtee -a でうまくいきました。

  • リダイレクト(>>):sudo だと工夫が必要。
  • sed:今回は \n が含まれるからだいぶめんどい。
  • tee:tee -a は追記モードらしい。

参考:sudoでリダイレクトをしたいとき - Y's note

ハマりどころ④:最初の行(初回)だけの置換え

タイムゾーン設定も変更したかったので sedUTC を置換えてしまえばいいと思ったのですが、初回のマッチだけ置きかえるには少し工夫が必要でした。

一番はじめだけ置換するには、sedの対象行を0行目から置換対象の行までに絞ればいい。つまりsed '0,/置換対象/ s/置換対象/置換後/'とする。

参考:sedでマッチする複数行のうちはじめの行だけ置換する方法 - grep Tips *

$ sudo cat /etc/sysconfig/clock | sed -e '0,/UTC/ s/UTC/Asia\/Tokyo/'
ZONE="Asia/Tokyo"
UTC=true

※Zoneはシステムクロックのタイムゾーン設定、UTC=true はハードウェアクロックの設定。

以上