#!/ bin / shまたは#!/ bin / bashを使用して、Ubuntu-OSXの互換性と使いやすさ、POSIXを実現します。


18

いずれかのスクリプトを最初の行として使用して、目的のシェルを呼び出すことができることを知っています。

#!/bin/sh、すべてのUNIXシステムとの互換性が絶対条件である場合にはお勧めできますか?

私の場合、私が気にしているOSはUbuntu(Debian)とOSXだけです。それを考えると、#!/bin/bash両方のシステムで使用できると確信できますか?
これにより、コマンドの構文がより近代的で明確なスクリプトを使用しやすくなりますか?#!/bin/sh使用はPOSIXの使用にも関連していますか?


1
おそらく多くのディストリビューションは、マージ開始していることは注目に値する/bin/usr/bin。その結果、#!/usr/bin/env <shname>最近の移植性のために使用する方がおそらく良いでしょう。
HalosGhost

回答:


15

手始めに、Bashがプリインストールされていると仮定できる場合(リストのすべてのシステムで私の知る限り)、以下のhashbangを使用して互換性を確保します。

#!/usr/bin/env bash

何これは呼び出すbashに関係なく、それは中のかどうか、設定する起こりません/bin/usr/local/bin

広範囲にわたるほとんどのシステム(AIX、Solaris、いくつかのBSDフレーバーを含む)ではbash、異なる場所に配置され、env常にに配置されました/usr/bin/env。ただし、このトリックは私のものではなく、Bash Cookbookの著者によるものです。

とにかく、はいBashはあなたの生活を楽にするいくつかの「近代的な」機能を使用できるようにします。

たとえば、二重括弧:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

一方、従来のシェル方言では、次のことに頼らなければなりません。

test -f "/etc/debian_version" && echo "This is a Debian flavor"

しかし、二重括弧についての最良の点は、マッチングのために正規表現を許可することです。バッシュハッカーウィキはその方向にあなたに多くのトリックを与えるだろう。

構文$((2**10))とインラインで、または他の算術式のような非常に便利な式を使用することもでき$((expression))ます。

少し時代遅れではありますが、サブシェルにバックティックを使用するのは問題ありません。ただし、$(command ...)呼び出しのネスト機能は、さまざまなサブシェルレベルで多くのことをエスケープする必要がないため、はるかに便利です。

これらは、Bashが従来の一般的なPOSIX sh構文に対して提供するもののほんの一部です。

ただし、シェルだけでなく(スクリプトだけでなく)シェルの機能を強化したい場合は、もご覧くださいzsh


Bashは非常に便利なツールですが、Bashスクリプトのバグ(例:access.redhat.com/security/cve/CVE-2014-6271)に対して脆弱な可能性のあるサービスの開始には使用しないように注意してくださいshそのようなタスクにこだわる。
リック-777

1
Rick-777その脆弱性は非常に誇張されており、私の意見ではあなたのコメントはFUDです。システムサービスがbashの下で実行されている場合、そのバグに対して脆弱ではありません。FastCGIのように、リモートユーザーが1つ以上の環境変数に直接アクセスできるようにし、パッチが適用されていないバージョンのbashでのみbashプロセスを分岐する場合にのみ、このバグに対して脆弱です。にshリンクされているシステムではbash、を使用しても脆弱性は緩和されませんsh
Score_Under July

11

DebianおよびUbuntuでは、/bin/shdashPOSIX準拠のシェルです。を指定する場合#!/bin/shは、スクリプト内のPOSIXステートメントに制限する必要があります。(利点は、dashよりも速く起動するbashため、スクリプトを短時間で実行できます。)

他の多くの(ほとんどの?)Linuxシステムで/bin/shbash、拡張機能#!/bin/shを使用しているにもかかわらず、多くのスクリプトがシェバン行として記述されているのは、ですbash

bash拡張機能を使用する場合、すべてのシステムで最も安全なアプローチは、指定すること#!/bin/bashです。そのようにすると、依存関係を明示的に示していますbash。あなたは必要 DebianとUbuntuの上でこれを実行します。追加ボーナスとして、/bin/sh bashいくつかの拡張機能を非アクティブ化するときに開始すると(詳細についてはbashPOSIXモードの説明を参照してください); そのため#!/bin/bash、を最大限に活用するには指定が必要ですbash

OS X /bin/bashでも利用可能/bin/shですbash#!/bin/bashそこでも指定はうまくいきます。


5

はい、OSXとLinuxの両方に付属してい/bin/bashます。あなたは完全に安全でなければなりません。ただし、これはPOSIX ではありません。POSIXシェルは/bin/shほとんどの(すべての?)システムにあり、それが最も移植性の高いアプローチであり、POSIX互換性を保つ唯一の方法です。

多くのシステムではを/bin/shポイントしますがbash、他のシステムでは異なるシェルをポイントできることに注意してください。dashたとえば、DebianやUbuntu へのシンボリックリンクです。また、/bin/shがへのリンクである場合でもbash、シェルの動作はsh(from man bash、emphasis mine)として呼び出されると変化します。

shという名前でbashが呼び出されると、POSIX標準にも準拠しながら、shの歴史的なバージョンの起動時の動作を可能な限り模倣しようとします。 対話型ログインシェル、または--loginオプション付きの非対話型シェルとして起動されると、最初に/ etc / profileと〜/ .profileからこの順序でコマンドを読み取って実行しようとします。--noprofileオプションを使用して、この動作を禁止できます。shという名前の対話型シェルとして呼び出されると、bashは変数ENVを探し、その値を展開します。
定義され、展開された値を読み取りおよび実行するファイルの名前として使用します。shとして呼び出されたシェルは、他のスタートアップファイルからコマンドを読み取って実行しようとしないため、-rcfileオプションは効果がありません。 shという名前で呼び出された非対話型シェルは、他の起動ファイルを読み取ろうとしません。shとして起動すると、bashは起動ファイルが読み込まれた後にposixモードに入ります。


2

「すべてのUnixシステム」との互換性が絶対的な要件である場合、およびそうでない場合、なぜシェルスクリプトを記述するのですか?-次に、はい、使用する必要があります#! /bin/sh。Bashは、どこにでもインストールできるとは限らないため/binです。

実際にはそれよりもはるかに悪いです。あなたに互換性が必要な場合は、すべてのUnixシステム、それは、SolarisおよびAIXのようなものが含ま彼らのシェル環境を凍結したあなたは昔ながらのようなものを使用しなければならないことを意味1995年頃sort +Nこと-構文新しいシステムが落ちてきましたの!また、シェル関数、配列、no [[ ... ]]、no ${foo#glob}$(( ... ))算術、no、$( ... )スタイルのコマンド置換、おそらく入力がどのくらい大きくなるかについての文書化されていない上限がないことも意味します...

あなたは、おそらくで悩まないで逃げることができ、そのくらいの互換性が、それは最初の場所でも、問題だ場合、私は強くあなたがシェル未満ひどい言葉を考えるお勧めします。基本的なPerlインタープリターがある以上バッシュよりも利用可能である可能性が高いです。


ありがとう。最初に述べたように、「私の場合、気にするOSはUbuntu(Debian)とOSXだけです」。これらは、過去5年間で私が使用した2つのシステムです(そして、私はそれらを頻繁に使用しています)。普遍的なスクリプトとそれがもたらす制限についてはまったく必要ありません。
マイケルデュラント

@MichaelDurrantその場合、シェルスクリプトを書く必要はありませんし、すべきではありません。代わりに、完全な移植性を必要としない場合のオプションである、より優れた多数のスクリプト言語のいずれかを使用する必要があります。
-zwol
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.