Ubuntuの/bin/shはbashではなくdash

dash is not bash

#!/bin/sh
offset=(`ls`)
echo $offset

みたいなシェルスクリプトがあって、こいつを Ubuntu で実行すると

$ ./foo.sh
./foo.sh: 2: ./foo.sh: Syntax error: "(" unexpected

というようにシンタックスエラーが発生した。shebang の /bin/sh ではなく /bin/bash として実行すると

$ bash foo.sh
$

とエラーにはならない。

シンタックス的に OK そうな foo.sh が一つ目ではなぜエラーになったかというと、ubuntu の /bin/sh は Almquist shell (ash) から派生したシェル Debian Almquist shell(dash) へのシンボリックリンクになっており、bash で OK な( … ) のシンタックスを dash は対応していないから。

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash
$ readlink -f /bin/sh
/bin/dash

bash と dash の互換・非互換問題は O’REILLY の “bash Cookbook” の著者の一人 JP Vossen さんがスライドにまとめてくれている。

bash vs. dash
http://princessleia.com/plug/2008-JP_bash_vs_dash.pdf

O'Reilly : bash cookbook

[ ... ] ではなく [[ ... ]] を使ったり、関数の定義に function func_name() ...function キーワードではじめても dash ではエラーとなる。

Ubuntu での dash シェルの採用

Ubuntu では 6.10 以降、ログインのシェルは bash にしたまま、デフォルトのシェルを bash から dash に変えている。
変更した狙いや移行の注意点は次の wiki にまとめられている

https://wiki.ubuntu.com/DashAsBinSh

Dash as /bin/sh
In Ubuntu 6.10, the default system shell, /bin/sh, was changed to dash (the Debian Almquist Shell); previously it had been bash (the GNU Bourne-Again Shell). The same change will affect users of Ubuntu 6.06 LTS upgrading directly to Ubuntu 8.04 LTS. This document explains this change and what you should do if you encounter problems.

The default login shell remains bash.

大きな狙いは、/bin/sh で実行するシェルスクリプトはもともと POSIX に準拠することになっており、dash は posix sh 互換な上に高機能な bash よりも コンパクトで起動も速いから。

/bin/sh 向けスクリプトで、POSIX に無い bash 固有の機能(bashism)はまさか使ってないよね、という性善説に基づいて移行したみたいだけど、世の中には悪い子さんもいるので都度対応してあげないといけない。

dash/bash 互換問題の回避方法

Ubuntu Wiki “DashAsBinSh” の “My production system has broken and I just want to get it back up!” のセクションにいくつかの解決策が書かれている

  • shebang を #!/bin/sh から #!/bin/bash に書き換える
  • 環境変数の SHELL を /bin/sh から /bin/bash に書き換える
  • sudo dpkg-reconfigure dash を実行して /bin/shbash にかえる(dash 固有の機能が使われていた場合は責任を持ちません!)

See Also

3 thoughts on “Ubuntuの/bin/shはbashではなくdash

Leave a comment