拡張 POSIX シェルスクリプト Advent Calendar 2013、19日目の記事です。 うおー、あと 30分で書かないといけねー! 雑な内容ですみません。
今日はポータブルなシェルスクリプトの書き方ついてざっくり語ります。 UNIX 系 OS であれば大抵の OS / バージョンでも動くシェルスクリプト!! (ただし外部コマンドの非互換性の問題は除く)
#!/bin/sh
で書く
POSIX sh でスクリプトを書けば完璧!
shebang は #!/bin/sh
!!
…全然完璧ではありません。Solaris 10 のように /bin/sh
が POSIX sh でない残念な
OS がまだ生き残っています。
マニュアルにも載っているバグが仕様になったのではないかと思われる謎挙動や未知のバグを回避するのが大変です。
ポータブルにするには #!/bin/sh
はまだ推奨できません。
#!/bin/ksh
で書く
ksh いいよ、ksh…。
何がいいかというと、大抵の商用 UNIX にデフォルトでインストールされています。 それ以外の Linux 系 OS などではデフォルトでは入っていないことが多いようですが、 大抵はコマンド一発でインストールされます。
ただし問題が 2つ。
問題一つ目。 ksh には大きくわけて 2つのバージョン、ksh 88 と ksh 93 があります (数字はリリースされた西暦下二桁)。 大きな違いは ksh 88 が連想配列をサポートしていない点ですが、 ほかにも色々と ksh 93 で拡張された機能があります。 よって、ポータブルにするには ksh 88 縛りにすることを推奨します。 ksh バージョン間の違いを把握するのが難しいようであれば、 POSIX sh 縛りで書けば(大抵は?)問題ありません。
問題二つ目目。 あれ、何だったっけ? 思い出したら追記します…。 ksh のクローンの一つ、mksh (とその源流 pdksh) の互換性が微妙って話だったっけ? mksh ではなく AT&T 派生の正統な ksh を使用しましょう。
#!/bin/bash
で書く
私、最近、Linux 向けの仕事しかしていません。
Linux と言えば大抵は /bin/sh
は /bin/bash
だし、そうでなくても
/bin/bash
はデフォルトで入っています。
商用 OS も bash が入っている時代です。
#!/bin/bash
で書けば大抵の仕事に対応できるね!!!1
…ただし bash もバージョン間の機能の違いは結構あります。 bash 特有の機能の利用は避け、POSIX sh 縛りで書くほうが安全です。
#!/bin/zsh
で書く
ないわー。
高機能だし、 zsh のデフォルトの挙動 はスクリプトを書きやすいような気がしますが、 ポータビリティを考えるとないかなー。
自前でビルドしてインストールできる人であれば、検討の余地はあると思います。
POSIX sh 縛りのシェルスクリプトの書き方
POSIX sh 縛りのシェルスクリプトを書くのに便利な checkbashisms
というコマンドがあります。引数にシェルスクリプトを指定すると、
bash 依存のコマンドや構文を指摘しまくってくれます。完璧ではありませんが、すごく便利!
Debian 系の OS であれば checkbashisms
は devscripts パッケージに含まれています。
(Fedora にはないのだろうか?)
# apt-get install devscripts
…
checkbashisms
は指定したスクリプトの shebang が #!/bin/sh
でない場合は
検査を省略するため、検査を強制するために --force
(-f
)
オプションを指定します。
例として、POSIX sh 非互換なシェルスクリプト、>突然の死<ジェネレーター echo-sd
を
checkbashisms
にかけてみましょう。
$ checkbashisms --force ~/bin/echo-sd
possible bashism in echo-sd line 102 (alternative test command ([[ foo ]] should be [ foo ])):
if [[ ${0##*/} == echo-sd ]] && [[ ${zsh_eval_context-toplevel} == toplevel ]]; then
possible bashism in echo-sd line 102 (should be 'b = a'):
if [[ ${0##*/} == echo-sd ]] && [[ ${zsh_eval_context-toplevel} == toplevel ]]; then
possible bashism in echo-sd line 105 ($BASH_SOMETHING):
case "${BASH_VERSION-}" in
possible bashism in echo-sd line 107 (type):
if type zsh >/dev/null 2>&1; then
possible bashism in echo-sd line 118 (typeset):
typeset SD_arg0="$0"
possible bashism in echo-sd line 119 (typeset):
typeset SD_copyright='(C) 2013 SATOH Fumiyasu @ OSS Technology Corp., Japan'
possible bashism in echo-sd line 120 (typeset):
…省略…
bash の拡張機能は ksh 由来のものが多いため、
#!/bin/ksh
なシェルスクリプトから ksh
依存度を検出するのにもある程度利用できます。
bashism?
「bashism」とは「bash]+「-ism」の造語で、「-ism」は 「主義」「理論」「慣行」「特性」などを意味します。 「POSIX sh にはない bash 特有の機能」という意味だと理解すれば正しいと思います。
- Bashism - Greg’s Wiki
ところで、12月25日はクリスマスな上に、
OSS 界隈で地味に活躍されているふみやすさんの誕生日ですね!
っ http://www.amazon.co.jp/registry/wishlist/27M7TV8CEEF6G?sort=priority
逆に、あなたの書いた OSS や Blog や Advent Calendar が気に入ったら何か送りたく なってしまうかもしれないので、プロフィールや Web サイトに あなたの Amazon 欲しいものリストの URL を貼っておいてくださいね!
私が勤める OSSTech っていう某弊社で社員募集しているようです。 人材紹介会社を介さなければ、入社後に 20万円のボーナス! 「ふみやすっていう人に紹介された」と言ってもらえると私にもボーナス!! → https://www.osstech.co.jp/recruit/
よろしければ、これまで参加した/参加予定のほかの Advent Calendar もどうぞ。
- Ansible Advent Calendar 2023
- シェル芸 Advent Calendar 2023
- 闇の魔術に対する防衛術 Advent Calendar 2023
- Ansible Advent Calendar 2023
- Ansible Advent Calendar 2020
- DNS温泉 Advent Calendar 2019
- OSSTech Advent Calendar 2019
- Ansible Advent Calendar 2018
- OSSTech Advent Calendar 2018
- Debian/Ubuntu Advent Calendar 2017
- Linux Advent Calendar 2017
- Shell Script Advent Calendar 2017
- Shell Script Advent Calendar 2016
- OpenLDAP と仲間たち Advent Calendar 2015
- Postfix Advent Calendar 2014
- 拡張 POSIX シェルスクリプト Advent Calendar 2013