シェルスクリプトにシバン(#!/bin/sh)はないほうがいいという説
Togetter投稿
「シェルスクリプトにシバン(#!/bin/sh)はないほうがいいという説」をトゥギャりました。 togetter.com/li/1077808
2017-02-04 17:32:05まとめを更新しました。 シバンがない場合,cshの対話シェルから起動されたら,shで再起動するにして,対応できたので,その話とサンプルコードを掲載。「シェルスクリプトにシバン(#!/bin/sh)はないほうがいいという説」 togetter.com/li/1077808
2017-02-25 13:19:41まとめを更新。cshの問題が解決。 これにより,Androidでもcshでも,文字エンコーディングにBOMがあっても動作する,より可搬性の高いシェルスクリプトの記述方法がみつかった。「シェルスクリプトにシバン(#!/bin/s.. togetter.com/li/1077808
2017-03-30 23:05:39発端
会社のNASサーバーでデータ処理をするためにシェルスクリプトを書いて試していたら,以下のPATH変数の初期化で getconf
コマンドが見つからないというエラーが出ていた。
export LC_ALL='C' PATH="$(command -p getconf PATH):$PATH"
会社のサーバーパソコン。ディストリビューション不明なのだけど、なんとgetconfがなかった。PATH変数の初期化でスクリプトが落ちていた。 えー。getconfないとかいったいどうしたらいいんだ…
2017-02-01 15:22:58@senopen unamw -aするとarmとかsmpとか表示された。なんだろう?こんなディストリビューションあるの?帰宅したら調べてみよう。
2017-02-01 16:03:51@senopen /etcの中にissueとかos-releaseとかというファイルがあったりしないだろうか。それからarmやsmpとはCPU構成のことではないだろうか。ARMのマルチコアとか……。
2017-02-01 17:00:08@col_richie os-releaseはなく、issueは以下の内容でした。 welcome to TS-231+, QNAP Systems, Inc。なんかベンダー独自ディストリビューションなのでしょうか。始めてみました。
2017-02-01 17:19:21@senopen 製品は qnap.com/ja-jp/product/… で(なるほど確かにarm smp)、OSは qnap.com/event/qts/jp/?… か……。 他にもPOSIX非準拠な点が多数あれば、そもそも準拠する気がない製品として無視してもよいかも。
2017-02-01 18:09:28@senopen もしかしてコマンドやシェルがBusyBox(コマンドが全て1つの実行ファイルへのハードリンク)になっていないだろうか。もしそうだったらさすがにPOSIX原理主義でも救いきれない。
2017-02-01 18:15:39@col_richie busybox使ってました。findとかreadlinkとかgrep, awk, sedなどなど。shはbashでした。busyboxはあまりPOSIX準拠してないのでしたっけ?調べないとわかりませんね…
2017-02-01 18:24:47@senopen あぁやっぱり。BusyBoxは、UNIXであることよりも、貧弱な組み込み環境でも必要最低限のことができることを優先しているので容赦なくPOSIX仕様を満たさないからなぁ。 BusyBoxで使えるコマンドはこちら→ busybox.net/downloads/Busy…
2017-02-01 18:29:35@col_richie げ!なんと!うーん。困りましたね… busybox採用している環境はそれなりにありそうなので、何のコマンドがどう準拠していないのか、把握しておいたほうがいい気がしますね…
2017-02-01 18:35:16@senopen BusyBoxの大半はPOSIXのサブセットなのでPOSIX原理主義のサブセット的な主義を立ち上げるという考えもあれど、その制約を緩和するためにGNU coreutilsコマンドの一部が入ってもいるので、結局BusyBoxはBusyBoxで独自の主義が要るかと…
2017-02-01 18:42:15@col_richie 独自の主義は不要と考えてます。 1. POSIXの定義が全てが常に有効というわけでもない 2. POSIX定義コマンドの全代替実装を把握したわけではない POSIXの乖離性がどれほどあるかわかりませんが,手間でなければBusyBoxをカバーしてもいいかなと
2017-02-01 22:33:21getconfが存在しない場合のPATH変数の初期化方法
実際にgetconfが存在しない環境がみつかった。サーバーなどパッケージングが厳選されているディストリビューションではgetconfコマンドが存在しないことはありえる。
こうした環境でもエラーが出ないようにコードの工夫を試みた。
ええーい。getconfがない場合でもうまくケアしたPATH変数の初期化方法はないものか。 なんとかうまくできないだろうか。あまり長ったらしくなく,やる方法だ。 こんな感じでどうだろうか? command -p $(command -v getconf || :) PATH
2017-02-01 22:53:42zsh対応
getconfが存在しない環境をケアした初期化方法は思いついたが,zshで動作しないという問題が生じた。
間違えた。こうやったら一応動く。 command -p $(command -v getconf || echo :) PATH でもzshだとcommand -p :がnot found。意味不明。
2017-02-01 22:59:36command -pって組み込みコマンドはダメなんだったっけ? -pオプション無しでもzshだとだめだ。 あれか。zshはPOSIX互換のオプションを有効にしないとアカン感じか。man zshmiscのcommandのヘルプ見たらexternal commandって書いてあった。
2017-02-01 23:05:09zshを考慮して完璧なPATH変数の初期化をやるなら。こうなる。 export PATH="$(command -p $((command -v getconf || echo true) | sed 's@.*/@@') PATH):$PATH" 1行に入りきらんぞ…どうしよう
2017-02-01 23:19:14command -pで絶対パスを指定してしまうと,そのパス指定が優先されてしまう。Solarisで結果が変わる。コマンド名だけだと,/usr/xpg6/binをみるけど,command -vだと/usr/xpg4/binをみにいってしまう。だから最後にsedで/を削除した。
2017-02-01 23:21:50