起きたこと
デプロイの手順書(bash)の表示の行 echo "== コンテナ($TAG)" で、set -u のスクリプトが止まりました。エラーの変数名の後ろに、化けた1文字が付いていました。
再現の手順
$ cat t1.sh
set -u
TAG=abc
echo "== コンテナ($TAG)"
echo "== braces(${TAG})"
$ /bin/bash t1.sh
t1.sh: line 3: TAG�: unbound variableset -u が無いと止まらず、括弧の残りの2バイトだけが出力されます(od -c で見ると、[ と ] の間に 0xBC 0x88 の2バイトだけが残る)。
$ printf 'TAG=abc\necho "[$TAG(]"\n' > t2.sh $ /bin/bash t2.sh | od -c 0000000 [ 274 210 ] \n
原因
「(」は UTF-8 で 0xEF 0xBC 0x88 の3バイトです。Mac の UTF-8 のロケールでは、bash が 0x80 以上のバイトを変数名に使える文字とみなし、$TAG の後ろの 0xEF までを変数名 TAG\xEF として読みます。そういう変数は無いので、set -u ではエラーに、無ければ空になり、残りの 0xBC 0x88 だけが出力されます。
直し方
全角の文字に接する変数は、波かっこで囲みます。
echo "== コンテナ(${TAG})"スクリプト全体を LC_ALL=C で動かしても起きませんが、ほかの日本語の処理に影響するので、波かっこで囲む方を勧めます。
確かめたこと
| 環境 | $TAG( | ${TAG}( |
|---|---|---|
| macOS 26.6・/bin/bash 3.2.57・LANG=C.UTF-8 | 止まる | 正しく出る |
| macOS 26.6・bash 5.2.37(Homebrew)・LANG=C.UTF-8/ja_JP.UTF-8/en_US.UTF-8 | 止まる | 正しく出る |
| macOS 26.6・上の2つ・LC_ALL=C | 正しく出る | 正しく出る |
| Debian 13(Linux)・bash 5.2.37・LANG=C.UTF-8 | 正しく出る | 正しく出る |
同じ bash 5.2.37 でも、Linux では起きませんでした。Linux で動かしたスクリプトを Mac で動かすと、ここで初めて止まることがあります。