[小ネタ] 日本語版Windows EC2のユーザーデータに日本語コメントを書いたら、スクリプトが1行も実行されなかった
こんにちは、林です。
とある案件で、Windows Server 2025のEC2をユーザーデータで初期設定していました。
タイムゾーンやファイアウォールの設定を並べたPowerShellスクリプトです。
引き継ぎを考えてコメントを日本語で書いたところ、ユーザーデータが1行も実行されなくなりました。ログを見てもエラーの内容までは書かれておらず、最初は原因の見当がつきませんでした。
先に結論
日本語コメントの直後の行が、コメントに巻き込まれて構文エラーになっていました。
EC2Launch v2が書き出したスクリプトを、日本語版WindowsのPowerShellがCP932として読むため、行末で改行が消えることがあります。ユーザーデータには日本語のコメントを書かないのが確実です。
今回の環境
| 項目 | 内容 |
|---|---|
| OS | Windows Server 2025日本語版 |
| EC2Launch | v2.5.2 |
| Windows PowerShell | 5.1.26100 |
| システムロケール | 日本語(CP932) |
| ユーザーデータの指定 | CloudFormationのUserData |
| スクリプトの改行コード | LF |
エラーの調べ方
次のユーザーデータでEC2を起動しました。日本語のコメント2行の直後にtry {があります。
<powershell>
Start-Transcript -Path C:\Windows\Temp\userdata.log -Append
# ICMP(ping)の受信許可
# 受信規則は既定で無効なので有効化する
try {
Enable-NetFirewallRule -Name "FPS-ICMP4-ERQ-In" -ErrorAction Stop
} catch {
Write-Output "failed: $_"
}
Stop-Transcript
</powershell>
起動しても、Start-Transcriptで作られるはずのC:\Windows\Temp\userdata.logがありません。
EC2Launch v2のログC:\ProgramData\Amazon\EC2Launch\log\agent.logを見ると、スクリプトがエラーを出力したことが分かります。
Info: Script file is created at: C:\Windows\system32\config\systemprofile\AppData\Local\Temp\EC2Launch2485221373\UserScript.ps1
Info: Error file is created at: C:\Windows\system32\config\systemprofile\AppData\Local\Temp\EC2Launch2485221373\err.tmp
Error: Script produced error output.
Info: Stage: postReadyUserData completed.
エラーの中身はerr.tmpに書き出されていたので、確認してみました。
発生場所 C:\Windows\system32\config\systemprofile\AppData\Local\Temp\EC2Launch2485221373\UserScript.ps1:5 文字:1
+ } catch {
+ ~
式またはステートメントのトークン '}' を使用できません。
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
try {は書いてあるのに、} catch {が「対応するtryがない」と判定されています。構文エラーなので、スクリプトは1行も実行されなかったようです。
対策
ユーザーデータで取れる対策は4つです。
日本語をコメントに書かない
英数字だけのコメントなら起きません。
改行コードをCRLFにする
行末にCRが入るため、改行が消えなくなります。ユーザーデータに書いた改行コードは、EC2Launch v2が書き出すファイルにもそのまま残ります。
テンプレートをLFで保存しているとLFのまま渡ります。エディタで改行コードをCRLFにして保存するか、Terraformで外部ファイルを読み込んでいる場合は渡すときに置き換えます。
user_data = replace(file("${path.module}/userdata.ps1"), "\n", "\r\n")
コメントは文字化けして表示されますが、PowerShellはコメント行を実行しないため、スクリプトの動作には影響しません。
スクリプトの先頭にBOMを入れる
EC2Launch v2が書き出すファイルにBOMが残るので、PowerShellがUTF-8として読みます。書き出されるのはタグの中身だけなので、BOMは<powershell>タグの直後に入れます。ただし、テンプレートに目に見えない文字を埋め込むことになります。
日本語コメントと実行行の間にASCIIだけの行を置く
# ----のような行を挟むと、消える改行がその行のものになるため、実行行は残ります。ただし、その行を消すと再発します。
私は最初この方法で直したのですが、あとからコメントを整理したときに罫線ごと消してしまい、また動かなくなりました。
原因
EC2Launch v2が書き出すスクリプトには、UTF-8の目印であるBOMが付いていません。Windows PowerShell 5.1はBOMがないファイルをCP932として読むので、UTF-8で書いたスクリプトがCP932として読まれます。
CP932の日本語は1文字2バイト、UTF-8の日本語は1文字3バイトです。
2バイトずつ読んでいくと切れ目がずれ、行末で1バイト余ることがあります。この1バイトが次の改行(0x0A)とセットで1文字として読まれ、改行が消えます。
今回は2つ目のコメント行がそうでした。
行末の「る」(E3 82 8B)の8Bが余り、改行を巻き込んでいます。
00000080 81 AE E3 81 A7 E6 9C 89 E5 8A B9 E5 8C 96 E3 81 ®ã§æå¹åã
00000090 99 E3 82 8B 0A 74 72 79 20 7B 0A 20 20 20 20 45 ã.try {. E
CP932として読むと、try {がコメント行の続きになります。9行あったスクリプトが8行になりました。
Get-Content C:\...\UserScript.ps1 -Encoding Default
Start-Transcript -Path C:\Windows\Temp\userdata.log -Append
# ICMP・・ing・峨・蜿嶺ソ。險ア蜿ッ
# 蜿嶺ソ。隕丞援縺ッ譌「螳壹〒辟。蜉ケ縺ェ縺ョ縺ァ譛牙柑蛹悶☆繧・try {
Enable-NetFirewallRule -Name "FPS-ICMP4-ERQ-In" -ErrorAction Stop
} catch {
Write-Output "failed: $_"
}
Stop-Transcript
どの行で起きるかは行末のバイト次第なので、コメントを書き換えると結果が変わります。動いていたスクリプトが、コメントを直しただけで動かなくなることもあります。
まとめ
日本語版Windows EC2のユーザーデータでは、日本語コメントの直後の行がコメントに巻き込まれて、スクリプト全体が動かなくなることがあります。BOMなしのUTF-8がCP932として読まれるのが原因で、コメントに日本語を書かないか、改行コードをCRLFにすれば避けられます。
ユーザーデータが動かなくても、エラーはどこにも表示されません。私も最初はスクリプトの中身ばかり見ていて、err.tmpに気づくのに時間がかかりました。同じ症状のときは、agent.logに書かれたパスをまず開いてみてください。
この記事がどなたかの参考になれば幸いです。最後までご覧いただきありがとうございました!
参考







