はじめに
/bin/sh は、Ubuntu と Redhat(RHEL)互換OS(CentOS,RockyLinux,AlmaLinux)ではシンボリックリンクであり、そのリンク先が次のように異なるシェルになっています。そのため、sh で実行されるシェルスクリプトは、Ubuntu と Redhat(RHEL)互換OSで挙動が異なることがあるので注意が必要です。
Ubuntu
/bin/sh -> dash
Redhat(RHEL)互換OS(CentOS,RockyLinux,AlmaLinux)
/bin/sh -> bash
bash と dash の違い
sh がリンクされている dash(Ubuntuの場合)と、bash(Redhat(RHEL)互換OSの場合)で、異なる点をいくつかあげます。
echo のエスケープシーケンス
\n といったエスケープシーケンスは、dashはデフォルトで解釈しますが、bashは -eオプションをつけた時のみ解釈します。
dash(Ubuntuの場合)
$ dash -c "echo 'a\nb'"
a
b
# dash で -e をつけると、それが出力されてしまう
$ dash -c "echo -e 'a\nb'"
-e a
b
bash(Redhat(RHEL)互換OSの場合)
$ bash -c "echo 'a\nb'"
a\nb
# -e をつけると、エスケープシーケンス処理して dash と同じになる
$ bash -c "echo -e 'a\nb'"
a
b
printf を使うと、両者ともエスケープシーケンス処理します。
dash(Ubuntuの場合)
$ dash -c "printf 'a\nb'"
a
b
bash(Redhat(RHEL)互換OSの場合)
$ bash -c "printf 'a\nb'"
a
b
関数定義時の function
関数定義では、dash では function の記述はサポートされませんが、bashではfunction の記述あり/なし両方サポートします。
dash(Ubuntuの場合)
# NG
function test(){
echo TEST
}
# OK
test(){
echo TEST
}
bash(Redhat(RHEL)互換OSの場合)
# OK
function test(){
echo TEST
}
# OK
test(){
echo TEST
}
シェルスクリプト実行
dash では . で読み込み実行します。カレントディレクトリのスクリプトでは ./スクリプト名 のように ./ が必要です。
bash では source , . 両方で読み込み実行します。カレントディレクトリのスクリプトでは ./ は不要です。
dash(Ubuntuの場合)
# OK
$ dash -c ". ./test.sh"
# NG
$ dash -c ". test.sh"
# NG
$ dash -c "source ./test.sh"
# NG
$ dash -c "source test.sh"
NG
bash(Redhat(RHEL)互換OSの場合)
# OK
$ bash -c ". ./test.sh"
# OK
$ bash -c ". test.sh"
# OK
$ bash -c "source ./test.sh"
# OK
$ bash -c "source test.sh"
その他
2008年とちょっと古いですが、bash と dash の違いが説明されています。
https://princessleia.com/plug/2008-JP_bash_vs_dash.pdf
参考
にわか管理者のためのLinux運用入門(317) Macで行く – bashとdashの違いを知る | TECH+(テックプラス)
bash – BashとDashでechoのエスケープシーケンスに対する挙動が異なるのは何故? – スタック・オーバーフロー
https://princessleia.com/plug/2008-JP_bash_vs_dash.pdf
コメント