まえがき
ひょんなことから、Linux(EC2インスタンス)からWindowsServerへbatを実行するコマンドを送信する機会があった。
需要があるかは微妙だけども、その方法を共有。
具体的には、AWS System Manager(SSM)のRunCommandを用いることで実現する。
検証環境
EC2インスタンス側: Amazon Linux AMI release 2018.03
WindowsServer: WindowsServer2012 R2
例
WindowsServerへのコマンド実行(ec2インスタンスより)
$ aws ssm send-command \
--document-name "AWS-RunPowerShellScript" \
--document-version "1" \
--targets "Key=instanceids,Values=${WindowsサーバのインスタンスID}" \
--parameters \
'{"workingDirectory":["${どこのディレクトリで実行するか}"],
"executionTimeout":["600"],
"commands":["${実行コマンド}"]
}' \
--timeout-seconds 600 \
--max-concurrency "50" \
--max-errors "0" \
--region ${リージョン}
コマンドを実行すると、レスポンスとして
"CommandId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
のようなパラメータが渡される。このパラメータを用い、実行結果の確認を行う。
SSMコマンド実行後の成否確認
$ aws ssm get-command-invocation \
--command-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
--instance-id "${windowsサーバのインスタンスID}" \
例えば、Linux環境からWindowsのC:直下でipconfigを実行したくなるときがあるかもしれない。
そんなときは WindowsServerへのコマンド実行 で述べたコマンドの変数を C:\\\\
と ipconfig
に変更し
-
aws ssm send-command
を実行 -
aws ssm get-command-invocation
を実行
と2ステップで実現することができる。
以下は、 get-command-invoction
を実行した際の返り値のサンプルとなる。
{
"Comment": "",
"ExecutionElapsedTime": "PT0.293S",
"ExecutionEndDateTime": "2020-01-01T00:00:00.000Z",
"StandardErrorContent": "",
"CloudWatchOutputConfig": {
"CloudWatchLogGroupName": "",
"CloudWatchOutputEnabled": false
},
"InstanceId": "${インスタンスID}",
"StandardErrorUrl": "",
"DocumentName": "AWS-RunPowerShellScript",
"DocumentVersion": "1",
"Status": "Success",
"StatusDetails": "Success",
"PluginName": "aws:runPowerShellScript",
"StandardOutputContent": "\r\nWindows IP �\\��\r\n...(以下略)",
"ResponseCode": 0,
"ExecutionStartDateTime": "2020-01-06T05:36:51.549Z",
"CommandId": "4b3ddb96-cec0-4df7-967e-81cc20d0d792",
"StandardOutputUrl": ""
}
コマンドの実行そのものに成功したかどうかは、 Status
を見ればよく、
実行したコマンドの返り値については、 StandardOutputContent
に格納される。
この返り値をパースするなりしてアレコレしたいところだが…以下問題点が
問題点
"StandardOutputContent": "\r\nWindows IP �\\��\r\n...(以下略)",
と言う文字列を見てわかるよう StandardOutputContent
の文字列が化ける…
Linux<->Windowsの行き来をする都合上、まあ文字化けするよね。
でもでも単純にnkfとかでエンコーディングすればいいじゃんと思いきや、試してみたところ、うまく変換されない(解決策あったら教えてほしい…)
# メインとなる処理はbatに任せておいて、そのbatを叩くだけって使い方が安牌?
注意点
このSSM経由でのコマンド実行は NT AUTHORITY\ System
で行われる。
想定する実行ユーザが異なることから、意図せずコマンドが実行できないことがあるので注意。
なお、もちろんSSM実行のポリシーをロールやらプロファイルで与えてあげないと、実行権限が無いですよと怒られるので、その点も注意。