概要
今日、シェルスクリプトをサーバーにデプロイしたところ、とある箇所で何故かexit 1
で終了してしまうコードがありました。
ローカルMacでは正常に終了することを確認していたので、わからなかったのですが調べて分かったことがあったので記録しておきます。
先に結論
MacOS15.4.1だとbashバージョンが低く(3系)、サーバーにインストールされているbashバージョン(AmazonLinuxやDebian12だと5系)と異なることで挙動が変わるので注意。
bashバージョンがサーバーと異なる場合は、homebrewでbashをインストールして挙動を確認しよう。
MacOSバージョン
- 15.4.1
コード
set -e
で戻り値が0でなければ、終了することを想定しています。
[[]]
は正規表現を使うために使用し、正規表現がマッチしなければ終了、マッチしたらecho
を実行することを想定しています。
#!/bin/bash
set -e
[[ "hoge" =~ "fuga" ]]
echo 'ok'
Macで実行してみます。
$ /bin/bash -x /tmp/test.sh
+ set -e
+ [[ hoge =~ fuga ]]
+ echo ok
ok
$ echo $?
0
set -e
により、戻り値が0以外なら終了するのですが、当該bashでは [[]]
の戻り値では判定されず、その後の echo
が実行されています。
同一のコードを Debian 12
で実行してみます。
※Debian12では/bin/sh
のシンボリックリンク先が dash
だったため、フルパスでbashを指定してます。
※Macも /bin/sh
は bash
になっているので注意
$ /bin/bash -x /tmp/test.sh
+ set -e
+ [[ hoge =~ fuga ]]
$ echo $?
1
この通り結果が異なります。
理由
bashのバージョンが異なるためです。
バージョン4系から set -e
および [[]]
の挙動が異なるようです。
※残念ながら日本語の公式ドキュメントを見つけられず、挙動が変わった正確なバージョンについては不確かです。英語ドキュメントでそれらしい情報があったものの、引用は避けています
Debian
$ /bin/bash --version
GNU bash, バージョン 5.2.15(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2022 Free Software Foundation, Inc.
Mac(default)
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin24)
Mac(homebrew)
$ /opt/homebrew/bin/bash --version
GNU bash, バージョン 5.2.37(1)-release (aarch64-apple-darwin23.4.0)
Copyright (C) 2022 Free Software Foundation, Inc.
$ /opt/homebrew/bin/bash -x /tmp/test.sh
+ set -e
+ [[ hoge =~ fuga ]]
$ echo $?
1
homebrewでインストールしたbashは5系でDebianと同一の挙動になりました。
まとめ
bashバージョンにより、set -e
および [[]]
の挙動が異なることがわかりました。
homebrewで最新版をインストールすることで、サーバーバージョンに近いバージョンをインストールできるので、homebrewでインストールしておくのが良さそうです。