web-dev-qa-db-ja.com

#!/ bin / bashを使用しなければならない場合と#!/ bin / shを使用する場合

シェルスクリプトで#!/bin/bash#!/bin/shより適切な場合

101
Hendré

要するに:

  • の上位集合を実装するシェルがいくつかあります - POSIX sh仕様 。異なるシステムでは、/bin/shはash、bash、dash、ksh、zsh、&cへのリンクになります。 (ただし、sh互換であることは決してありません - 決してcshや釣りをしないでください。)

  • shの機能だけに固執する限り、#!/bin/shを使用することができ(そしておそらくそうすべきです)、スクリプトはどのシェルであっても問題なく動作するはずです。

  • Bash固有の機能(配列など)を使い始める場合は、特にbashを要求する必要があります。なぜなら、/bin/shがすでに自分のシステムでbashを起動していても、そうでないかもしれません他のみんなのシステムで、あなたのスクリプトはそこで実行されないでしょう。 (もちろん同じことがzshとkshにも当てはまります。)/ bをチェックするために shellcheck を使うことができます。

  • スクリプトが個人的な使用のみを目的としている場合でも、アップグレード中にいくつかのOSが/bin/shを変更することに気付くかもしれません。 Debianでは以前はbashでしたが、後になってごくわずかなダッシュに置き換えられました。バシズムを使っていたが#!/bin/shを持っていたスクリプトは突然壊れた。

しかしながら:

  • #!/bin/bashでもそれほど正しくありません。異なるシステムでは、bashは/usr/bin/usr/pkg/bin、または/usr/local/binに存在するかもしれません。

  • より信頼性の高いオプションは#!/usr/bin/env bashです。これは$ PATHを使用します。 (envツール自体も厳密には保証されていませんが、/usr/bin/env/bin/bashよりも多くのシステムで動作します。)

147
grawity

スクリプトの開発とデバッグに実際に使用したシェルに対応するShebangを使用してください。すなわちあなたのログインシェルがbashで、あなたがあなたの端末で実行可能ファイルとしてあなたのスクリプトを実行するなら、#!/bin/bashを使用してください。あなたが配列(あるいはあなたが知っているどんなbash機能でも)を使ったことがないので、あなたが好きなシェルを選んでも大丈夫だと仮定しないでください。シェルの間には微妙な違いがたくさんあります(echo、関数、ループ、名前を付けます)。これらは適切なテストなしでは発見できません。

これを考えてみましょう。もしあなたが#!/bin/bashを去り、あなたのユーザーがそれを持っていなければ、彼らは明確なエラーメッセージを見るでしょう。

Error: /bin/bash not found

ほとんどのユーザーは、適切なパッケージをインストールすることで1分以内にこれを修正できます。一方、Shebangを#!/bin/shに置き換えて/bin/sh/bin/bashへのシンボリックリンクであるシステムでテストすると、bashを持たないユーザーは問題を抱えることになります。彼らはたぶん以下のような不可解なエラーメッセージを見るでしょう:

Error in script.sh line 123: error parsing token xyz

これは修正するのに何時間もかかるかもしれません、そして、彼らがどのシェルを使用するべきであるかについての手がかりはありません。

Shebangで別のシェルを使用したい理由はそれほど多くはありません。その理由の1つは、あなたが使ったシェルが普及していないことです。もう1つは、いくつかのシステムではかなり速いshでパフォーマンスを向上させることです。そしてあなたのスクリプトはパフォーマンスのボトルネックになります。その場合は、対象のシェルでスクリプトを徹底的にテストしてからShebangを変更してください。

18

#! /bin/shのみを使用する必要があります。

シェルスクリプトでbash(またはzsh、またはfish、...)拡張機能を使用しないでください。

シェル言語のany実装(シェル自体に付随するすべての「ユーティリティ」プログラムを含む)で動作するシェルスクリプトのみを記述してください。最近はおそらく取ることができます POSIX.1-2001not -2008)シェルおよびユーティリティの機能について権限がありますが、いつの日かシェルおよびユーティリティが1992年頃に凍結されたレガシーシステム(SolarisまたはAIXなど)にスクリプトを移植するよう求められる場合があることに注意してください。

まじで?

はい、真剣に。

シェルはひどいプログラミング言語です。唯一の目的は、/bin/sheveryUnixインストールが保証されている唯一のスクリプトインタープリターであることです。

もう1つあります:コアPerl 5インタープリター(/usr/bin/Perl)の一部の反復は、ランダムに選択されたUnixインストールで(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bashよりもmore入手可能ですです。その他の優れたスクリプト言語(Python、Ruby、node.jsなど—シェルと比較する場合、そのカテゴリにPHPとTclを含めます)も、bashやその他の拡張シェルとほぼ同じくらい利用可能です。

したがって、bashスクリプトを記述するオプションがある場合、ひどくはないプログラミング言語を使用するオプションがあります。

さて、simpleシェルスクリプトは、cronジョブなどからシーケンスでいくつかのプログラムを実行するだけですが、シェルスクリプトのままにしておくことは問題ありません。ただし、単純なシェルスクリプトには、配列や関数、または[[さえ必要ありません。そして、complicatedシェルスクリプトは、他に選択肢がない場合にのみ記述する必要があります。たとえば、Autoconfスクリプトは、適切なシェルスクリプトです。ただし、これらのスクリプトは、構成中のプログラムに関連する/bin/shevery化身で実行する必要があります。つまり、拡張機能は使用できません。最近の古いプロプライエタリなUnixを気にする必要はないでしょうが、おそらくshould現在のオープンソースBSDを気にするでしょう。デフォルトではbashをインストールしない最小限のシェルとbusyboxのみを提供する組み込み環境。

結論として、移植性のあるシェル言語では利用できない機能を探している機能は、スクリプトが複雑すぎてシェルスクリプトを維持できないことを示しています。代わりに、より良い言語で書き直してください。

6
zwol

一般的に、機能より時間が重要な場合は、より速いシェルを使用します。 shはしばしばダッシュにエイリアスされ、(ナノ)秒ごとにカウントされるrootのcronタスクやバッチ操作に使用される傾向があります。

4
mckenzm

もっと簡単に言うと、ほとんどのシステムでの移植性が最も重要な場合はshを使用し、bashのバージョンでサポートされている場合は配列などの特定の機能を使用する場合はbashを使用します。

3
  • sh(ほとんどの場合)、特に必要な場合はbash(またはkshなど)

最も安全な方法です。ハードコーディングされた場合は、/ usr/bin/shellOfChoiceになりますが、私は今、いつも使用しようとしている新しい規則を変更します。

#!/ usr/bin/env shまたは
#!/ usr/bin/env bash
またはPerlスクリプトなど
#!/ usr/bin/env Perl-w

もちろん、スクリプトが自動的に新しいPATHを取らないようにする理由がある場合は、それをハードコーディングし続けます。そして、/ usr/bin/somethingが最も使用されるパスになるはずです。

1
Michael Felt