目次
はじめに
こんにちは、クラウド事業部の菅です。
以前、CloudFormationでSSMドキュメントを作成したことがあったのですが、テンプレートファイルの作成で困ったことがありました。
CloudFormationでSSMドキュメントを作成する場合、スクリプトを文字型配列として定義する必要があります。
この、スクリプトを文字型配列として定義する作業を、少ない作業量かつ管理しやすい形式で行うために試行錯誤しましたのでご紹介します。
準備
以下のスクリプトを例にご紹介します。
※ShellScriptを使用していますが、PowerShellScriptでも同じ方法で定義できます。
#!/bin/bash
width=200
width_column=$((width/3))
echo "# Check updatable packages"
dnf repoquery --upgrades --latest-limit 1 --queryformat="%{name} %{version}-%{release}" |
awk '{
"dnf repoquery --installed --queryformat=\"%{version}-%{release}\" "$1 | getline version
printf "%-'$width_column's%-'$width_column's%-'$width_column's\n", $1,version,$2
}'
このスクリプトは、更新可能なパッケージをパッケージ名・現在のバージョン・更新可能な最新バージョンの順で出力するものです。
sh-5.2$ # script.shにスクリプトを保存
sh-5.2$ ./script.sh
# Check updatable packages
Last metadata expiration check: 0:02:29 ago on Fri May 9 02:20:27 2025.
httpd 2.4.54-3.amzn2023.0.4 2.4.62-1.amzn2023
httpd-core 2.4.54-3.amzn2023.0.4 2.4.62-1.amzn2023
httpd-filesystem 2.4.54-3.amzn2023.0.4 2.4.62-1.amzn2023
httpd-tools 2.4.54-3.amzn2023.0.4 2.4.62-1.amzn2023
mod_lua 2.4.54-3.amzn2023.0.4 2.4.62-1.amzn2023
rsyslog 8.2204.0-3.amzn2023.0.2 8.2204.0-3.amzn2023.0.4
rsyslog-logrotate 8.2204.0-3.amzn2023.0.2 8.2204.0-3.amzn2023.0.4
sh-5.2$
SSMドキュメント化
方法1:手動で変換する
スクリプトを手動で文字列に変換してテンプレートファイルを作成する方法です。
今回のスクリプトでは、Powershellを使用して以下のように変換を行いました。
PS C:\Users\user\Downloads> # script.txtにスクリプトを保存
PS C:\Users\user\Downloads> (gc script.txt) -Replace "\\","\\" -Replace "`"","\`"" -Replace "^(.*)$","`"`$1`""
作成したテンプレートファイルおよびSSMドキュメントは以下の通りです。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SsmDocument:
Type: AWS::SSM::Document
Properties:
Name: apc-kan-test-document
DocumentFormat: YAML
DocumentType: Command
Content:
schemaVersion: '2.2'
mainSteps:
- action: aws:runShellScript
name: ListUpdatablePackages
precondition:
StringEquals:
- platformType
- Linux
inputs:
timeoutSeconds: '60'
runCommand:
- "#!/bin/bash"
- ""
- "width=200"
- "width_column=$((width/3))"
- ""
- "echo \"# Check updatable packages\""
- "dnf repoquery --upgrades --latest-limit 1 --queryformat=\"%{name} %{version}-%{release}\" |"
- "awk '{"
- " \"dnf repoquery --installed --queryformat=\\\"%{version}-%{release}\\\" \"$1 | getline version"
- " printf \"%-'$width_column's%-'$width_column's%-'$width_column's\\n\", $1,version,$2"
- "}'"

SSMドキュメントを作成することができましたが、この方法には以下の問題があります。
- スクリプトの変換が必要
- ダブルクォーテーションなどのエスケープによりテンプレートファイルの可読性が低下する
今回のスクリプトは短いため簡単に変換できましたが、複雑なスクリプトでは変換に失敗した場合に問題個所を特定することが困難になります。
また、テンプレートファイルには変換後のスクリプトが定義されるため可読性が低下してしまいます。
方法2:パイプ(|)を使用して複数行を文字列として認識させる
方法1では、変換後のスクリプトを定義することが問題となっていましたので、変換せずに定義する方法を調べました。
EC2のUserData定義時など、パイプを使用して複数行を文字列として認識させていましたので、パイプを使用して定義してみました。
作成したテンプレートファイルおよびSSMドキュメントは以下の通りです。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SsmDocument:
Type: AWS::SSM::Document
Properties:
Name: apc-kan-test-document
DocumentFormat: YAML
DocumentType: Command
UpdateMethod: NewVersion
Content:
schemaVersion: '2.2'
mainSteps:
- action: aws:runShellScript
name: ListUpdatablePackages
precondition:
StringEquals:
- platformType
- Linux
inputs:
timeoutSeconds: '60'
runCommand:
- |
#!/bin/bash
width=200
width_column=$((width/3))
echo "# Check updatable packages"
dnf repoquery --upgrades --latest-limit 1 --queryformat="%{name} %{version}-%{release}" |
awk '{
"dnf repoquery --installed --queryformat=\"%{version}-%{release}\" "$1 | getline version
printf "%-'$width_column's%-'$width_column's%-'$width_column's\n", $1,version,$2
}'

変換処理を行うことなくテンプレートファイルを作成することができました。
ですが、方法1とは異なりSSMドキュメント内のコマンドがすべて1行で定義されています。
この状態でも実行は可能ですが、可読性が著しく低下します。
方法3:パイプとSplit関数を使用する
方法2ではSSMドキュメントの可読性が低下してしまいましたが、パイプを使用したことで各行末に改行記号(\n)が自動挿入されていました。
そこで、改行記号を区切り文字としてSplit関数で文字列を分割してみました。
作成したテンプレートファイルおよびSSMドキュメントは以下の通りです。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SsmDocument:
Type: AWS::SSM::Document
Properties:
Name: apc-kan-test-document
DocumentFormat: YAML
DocumentType: Command
UpdateMethod: NewVersion
Content:
schemaVersion: '2.2'
mainSteps:
- action: aws:runShellScript
name: ListUpdatablePackages
precondition:
StringEquals:
- platformType
- Linux
inputs:
timeoutSeconds: '60'
runCommand:
Fn::Split:
- "\n"
- |
#!/bin/bash
width=200
width_column=$((${width}/3))
echo "# Check updatable packages"
dnf repoquery --upgrades --latest-limit 1 --queryformat="%{name} %{version}-%{release}" |
awk '{
"dnf repoquery --installed --queryformat=\"%{version}-%{release}\" "$1 | getline version
printf "%-'$width_column's%-'$width_column's%-'$width_column's\n", $1,version,$2
}'

変換処理を行うことなく、方法1と同じSSMドキュメントを作成することができました。
自動挿入される改行記号のみ区切り文字とし、スクリプト内の改行記号は区切り文字として扱われていません。
RunCommandを使用して作成したSSMドキュメントを実行してみます。


実行も問題なさそうです。
まとめ
今回はスクリプトをSSMドキュメント化するために試行錯誤した内容をご紹介しました。
やっていることは単純ですが、手動で変換する方法に比べて作業量や管理面で利点があります。
この記事が誰かのお役に立てば幸いです。
お知らせ
APCはAWS Advanced Tier Services (アドバンストティアサービスパートナー) 認定を受けております。
その中で私達クラウド事業部はAWSなどのクラウド技術を活用したSI/SESのご支援をしております。
また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。