AWS SystemsManager(SSM)のRun Commandを使用するとEC2にSSH接続しなくてもシェルコマンドを実行することができます。今回はboto3(Python)から実行してみたので設定手順とサンプルコマンドを紹介します。

結論(設定手順)
- EC2にSystemsManager(SSM)の権限をロールで付与する
- EC2のSystemsManagerエージェントを更新する(大体のEC2には初期インストールされているので更新のみ)
- boto3のsend_commandでRun Commandを実行する
次章から順を追って説明します。
準備 EC2にロールを設定する
EC2でRun Commandを実行するにはEC2にIAMロールをアタッチする必要があります。
IAMロールの作成
IAMコンソールからロールを作成します。EC2で使用するのでEC2にチェックを入れます。

次の画面でAWS管理ポリシーのAmazonEC2RoleforSSMを選択します。

適当な名前を付けてロールを作成します。筆者はポリシーと同じ名前「AmazonEC2RoleforSSM」にしました。

作成したポリシーをEC2にアタッチする
EC2のコンソールに移動し、対象のEC2にIAMロールをアタッチします。

ロールは先ほど作成したロールを選択します。

準備 EC2のSystemsManagerエージェントをアップデートする
SystemsManagerエージェントのアップデートもSystemsManager Run Commandで実行できます。
コンソールでSystemsManagerを開き、Run Commandを選択します。右上のRun commandを選択します。

フィルタにAWS-UpdateSSMAgentを入力し、AWS-UpdateSSMAgentを選択します。

対象のEC2インスタンスを選択します。ここに出てこない場合はロールの設定が正しく実施されていない可能性があります。
ロールをアタッチしてもインスタンスの表示がすぐにはされないことがあります。そんな時はロールをアタッチ後にEC2インスタンスを再起動すると認識されることがあるようです。
また、EC2からのアウトバウンド通信が制限されているとインスタンスが表示されないことがあります。その際は外部サイトですが、こちらの記事が参考になります。

他の項目はそのままでOKです。実行ボタンを押下します。

少し待って更新すると成功します。

boto3でRun Commandを実行する
実行ユーザの権限設定
Lambdaから実行する場合はLambdaロールの設定、ローカルから実行する場合はアクセスキーのユーザの権限を設定します。AdministratorAccessポリシーをアタッチしている場合は動作しますが、最低限SystemsManager Run Commandの権限とS3のPut権限は必要です。
S3の権限が必要なのはRun Commandの実行結果ログをS3バケットにPUTするからです。S3への実行結果配信が不要な場合はS3への権限とsend_commandへのS3関連の引数(OutputS3XXX)も不要です。
筆者動作確認ではAmazonS3FullAccessとAmazonSSMFullAccessのポリシーをアタッチしたIAMユーザのアクセスキーを使ってプログラムを実行しました。(AWSのベストプラクティス的にはフルアクセスではなく、権限を絞ったほうが良いかと思いますが、ご容赦ください。)
2023/04追加 RunCommandに関しては以下の権限(IAMポリシー)で実行することができました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ssm:ListCommands",
"ssm:SendCommand",
"ssm:ListCommandInvocations"
],
"Resource": "*"
}
]
}
サンプルプログラムと実行
以下のようなプログラムでRun Commandを実行できます。冒頭4-7行目のインスタンスIDやS3情報は各々書き換えてください。
また、実行したいコマンドをcommandsの配列に記入してください。(17-19行目)サンプルコードでは適当にmariaDBの再起動とpwdコマンドとpsコマンドを実行しています。
import boto3
import time
# インスタンスIDやバケットの情報は各自書き換える。
instance_id = "i-xxxxxxxxxxxxx"
outputs3_region='ap-northeast-1'
outputs3_bucketname='S3buketname'
outputs3_keyprefix='keyprefix'
ssm = boto3.client('ssm')
# Run Command実行
response = ssm.send_command(
InstanceIds = [instance_id],
DocumentName = "AWS-RunShellScript",
Parameters = {
"commands": [
"sudo systemctl restart mariadb",
"pwd",
"ps"
]
},
OutputS3Region = outputs3_region,
OutputS3BucketName = outputs3_bucketname,
OutputS3KeyPrefix = outputs3_keyprefix
)
# 処理待ち
time.sleep(5)
# Run Command実行結果からCommandId取得
command_id = response['Command']['CommandId']
# CommandIdからコマンドの実行結果取得
response = ssm.list_command_invocations(
CommandId = command_id,
Details = True
)
# 実行結果出力
print(response['CommandInvocations'][0]['Status'])
# 実行結果からコンソール出力をprint
print(response['CommandInvocations'][0]['CommandPlugins'][0]['Output'])
サンプルコマンドをそのまま実行すると以下のようにpwdの結果とpsコマンドの結果が返ります。(mariaDBの再起動はコンソール出力されないので出ていません。)
PS C:\Users\User\work\python> python3 .\runcommandTest.py
Success
/usr/bin
PID TTY TIME CMD
1 ? 00:00:03 systemd
以下略
解説
boto3のsend_commandを使ってRun Command実行し、実行結果をlist_command_invocationsで取得しています。
以下はsend_commandでRun CommandでAWS-RunShellScriptドキュメントを実行している個所です。ドキュメントの引数に実行したいコマンドを指定できます。S3情報(OutputS3Region、OutputS3BucketName、OutputS3KeyPrefix)を指定することで出力をS3に格納することができます。
# Run Command実行
response = ssm.send_command(
InstanceIds = [instance_id],
DocumentName = "AWS-RunShellScript",
Parameters = {
"commands": [
"sudo systemctl restart mariadb",
"pwd",
"ps"
]
},
OutputS3Region = outputs3_region,
OutputS3BucketName = outputs3_bucketname,
OutputS3KeyPrefix = outputs3_keyprefix
)
マネジメントコンソールからAWS-RunShellScriptを実行する際はコマンドのパラメータとしてシェルコマンドを実行できますが、boto3ではcommandsに配列で渡すイメージになります。

以下は実行したコマンドの実行結果を取得しています。
response = ssm.list_command_invocations(
CommandId = command_id,
Details = True
)
# 実行結果出力
print(response['CommandInvocations'][0]['Status'])
response[‘CommandInvocations’][0][‘Status’]には成功(Success)や失敗(Failed)が入ります。sleepが短すぎる場合は実行中(InProgress)が表示されたりします。
他にもステータスがありますが詳しくはlist_command_invocationsドキュメントをご確認ください。

さいごに(感想)
EC2を使用するシステムではRun Commandを用いることでソフトの更新やプロセスの修復、再起動もできて便利だと感じました。よくある外形監視プログラムで異常があったらEC2に入って特定のコマンドを実行するといった今まで人が行っていたことを自動化できそう。今後Run Commandの応用例も記事にできたらと思います。
PR
当ブログはWordPressテーマSWELLを使用しています。非常に使いやすく、簡単にプロのようなデザインを使えるのでお勧めです!!
SWELL – シンプル美と機能性両立を両立させた、圧巻のWordPressテーマ

システムエンジニア
AWSを中心としたクラウド案件に携わっています。
IoTシステムのバックエンド開発、Datadogを用いた監視開発など経験があります。
IT資格マニアでいろいろ取得しています。
AWS認定:SAP, DOP, SAA, DVA, SOA, CLF
Azure認定:AZ-104, AZ-300
ITIL Foundation
Oracle Master Bronze (DBA)
Oracle Master Silver (SQL)
Oracle Java Silver SE
■略歴
理系の大学院を卒業
IT企業に就職
AWSのシステム導入のプロジェクトを担当