#!/ usr / bin / env bashが#!/ bin / bashよりも優れているのはなぜですか?


212

このサイトの推奨事項(推奨されるBashシバンは何ですか?)を含め、いくつかの場所で、#!/usr/bin/env bashに優先して使用するのを見てきました#!/bin/bash。私は、1人の進取的な個人が使用#!/bin/bash間違っていて、そうすることによってbash機能が失われることを示唆するのを見たことさえあります。

そうは言っても、私は厳しく管理されたテスト環境でbashを使用します。この環境では、循環しているすべてのドライブが基本的に単一のマスタードライブのクローンです。私の場合は必ずしも適用可能ではありませんが、私は移植性の議論を理解しています。他のものよりも好む他の理由はありますか#!/usr/bin/env bash、そして、移植性が懸念であると仮定して、それを使用することは機能性を壊すことができる理由がありますか?


7
必ずしも良いとは限りません。unix.stackexchange.comでこの質問私の回答を参照してください。(私はこれを複製として閉じるように投票しますが、サイト間でそれを行うことはできないと思います。)
キース・トンプソン

2
@ziggの答えに加えて、envに位置していない可能性があります/usr/bin。シバンコメントは完全に悪い考えです私見。デフォルトのスクリプトインタープリターがシバンコメントを処理しない場合、それは単なるコメントです。ただし、スクリプトインタープリターがシバンコメントを処理できることがわかっていて、bashへのパスがわかっている場合は、パスが長すぎる(可能性が低い)か、スクリプトを移植する可能性がない限り、絶対パスを使用して呼び出さない理由はありません。 / binにbashがないシステムに。繰り返しになりますが、この場合、移植性が関係するため、前述の警告が適用されます。

1
@KeithThompson、リンクをありがとう。おそらく、質問を投稿する前の回答に対する私の検索は少し狭かったです。これらすべてからの私の持ち帰り:(1)linux / unix / posix / etc ...は灰色であり、(2)絶対に正しい答えを持っていると主張している人は、絶対に特定のシナリオに対して正しい答えを持っています。
spugm1r3 2014

3
POSIX / Unixでの多くの動作は明確に定義されています。場所は必ずしもそれほど明確ではありません。/etcまたはのようなものが存在する必要があり/bin/shます。bashほとんどのUnixライクなシステム用のアドオンです。Linuxだけがbash存在することが保証されており、/binおそらくとしてもリンクされてい/bin/shます。Linuxが多くの人々にとって現代の事実上のUnixになって以来、Linux以外のシステムが存在する可能性があるという事実は忘れられてきました。以下の私自身の回答では、あなたが言っbashたのでLinuxを想定しました。私が使用したBSDボックスの多くは、インストールされていませんでした。
Sean Perry、

2
@キース-Bashの場合(他の質問のPythonとは対照的に)... OpenBSDにははありません/bin/bash。Bashはデフォルトではインストールされません。あなたがそれを望むなら、あなたはしなければなりませんpkg install bash。インストールすると、に配置され/usr/local/bin/bashます。/bin/bashOpenBSDには何もインストールされていません。#!/bin/bash意志のシバンは誤り、そして#!/usr/bin/env bash成功するでしょう。
jww

回答:


229

#!/usr/bin/envPATHを検索しますがbashbash常にではありません/bin。特にLinux以外のシステムでは。たとえば、私のOpenBSDシステム/usr/local/binでは、オプションパッケージとしてインストールされているため、にあります。

あなたが絶対に確実でbashあり、/bin常にそうであるなら、それを直接あなたのシバンに置くことには害はありません—しかし私はそれをお勧めします。


29
何についてのenv場所?POSIXはそれを強制しません。
Julio Guerra、2016

1
@JulioGuerra メールの処理に/usr/lib/sendmail(または最近では/usr/sbin/sendmail)バイナリを使用できるのと同じように/usr/bin/env、envシバンが非常に一般的であるため、Unixライクなシステムで最も重要です。これは事実上の標準インターフェースです。
zigg

8
@ziggそれはとてもUN * Xです... <-:つまり、の標準の場所を持っていることは彼らにとって最も興味深いことですが、envの標準の場所(単なるソフトリンクにすることができます)を持たないことがどういうわけかbash。言うまでもなく、hashbangがをまったく受け入れず#!bash、を使用するのPATHではなく、を使用しenvます。新人のために十分に混乱させていないと思います。
ddekany 2018

1
@JulioGuerraウィキペディアによると、あなたは本当です:「保証されている」わけではありません。代わりに、「可能性が高い」ようです。ウィキペディアはThis mostly works because the path /usr/bin/env is commonly used for the env utilityここでen.wikipedia.org/wiki/Shebang_(Unix)と言っています-私たちenvはすべてのシステムに「おそらく」そこにあると確信しなければなりません。
Xavi Montero 2018年

2
@XaviMontero:私envは、/binではなくにあるシステムを使用しました/usr/bin(どのシステムか、おそらくSunOS 4かはわかりません)。最近で/usr/bin/envは、#!/usr/bin/envハックの人気のために、それが利用できる可能性が非常に高くなっています。
キーストンプソン、

39

bashの標準的な場所は/binで、私はそれがすべてのシステムに当てはまると思います。ただし、そのバージョンのbashが気に入らない場合はどうなりますか?たとえば、bash 4.2を使用したいのですが、私のMacのbashは3.2.5です。

私はbashを再インストールしてみる/binことができますが、それは悪い考えかもしれません。OSをアップデートすると上書きされます。

ただし、bashをにインストールし/usr/local/bin/bashて、PATHを次のように設定できます。

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

ここで、を指定した場合bash、古いものはで取得できません/bin/bashが、より新しくて光沢のあるものはで取得でき/usr/local/binます。いいね!

私のシェルスクリプトがその!# /bin/bashシバンを除いて。したがって、シェルスクリプトを実行すると、連想配列さえもない、古くてお粗末なバージョンのbashが得られます。

を使用/usr/bin/env bashすると、PATHにあるバージョンのbashが使用されます。PATHを設定して/usr/local/bin/bash実行すると、それがスクリプトで使用するbashになります。

bashでこれを確認することはまれですが、PerlとPythonの方がはるかに一般的です。

  • 安定性に重点を置いた特定のUnix / Linuxリリースは、これら2つのスクリプト言語のリリースで遅れることがあります。少し前まで、RHELのPerlは5.8.8でした-8年前のバージョンのPerlです!誰かがよりモダンな機能を使用したい場合は、独自のバージョンをインストールする必要がありました。
  • PerlbrewやPythonbrewなどのプログラムを使用すると、これらの言語の複数のバージョンをインストールできます。これらは、PATHを操作して必要なバージョンを取得するスクリプトに依存しています。パスをハードコーディングすると、brewでスクリプトを実行できなくなります。
  • PerlとPythonがほとんどのUnixシステムに含まれている標準パッケージではなかったのは、それほど昔ではありません(そう、それはずっと前です)。つまり、これらの2つのプログラムがインストールされている場所がわからないということです。下だった/bin/usr/bin/opt/bin?知るか?使用#! /usr/bin/env perlすることは、私が知る必要がなかったことを意味しました。

そして今なぜあなたは使うべきではないのか #! /usr/bin/env bash

パスがシバンにハードコードされている場合、そのインタープリターで実行する必要があります。したがって、#! /bin/bashデフォルトでインストールされているバージョンのbashを使用するように強制します。bash機能は非常に安定しているため(Python 3.xで2.xバージョンのPythonスクリプトを実行してみてください)、特定のBASHスクリプトが機能しない可能性はほとんどありません。また、私のbashスクリプトはおそらくこのシステムや他のシステムで使用されているためです、bashの非標準バージョンを使用すると、望ましくない影響が生じる可能性があります。シェルスクリプトでbashの安定した標準バージョンが使用されていることを確認したい場合がほとんどです。したがって、おそらく私はシバンにパスをハードコーディングしたいと思います。


5
これは真実ではありません:「bashの標準の場所は/ binです」(標準のドキュメントを引用できない場合)、ほとんどのLinuxディストリビューションとmacosの「通常の」場所よりも正確である可能性がありますが、UNIXシステムの一般的な標準(特に、ほとんどの* bsdsの場所ではありません)。
tesch1

13

呼び出すbashには、少しやり過ぎです。bash〜/ binにあなた自身のような複数のバイナリがある場合を除いて、それはあなたのコードが$ PATHが正しいものを持っていることに依存していることも意味します。

こんなものにも重宝しpythonます。python使用されている代替バイナリにつながるラッパースクリプトと環境があります。

ただし、バイナリが本当に必要なバイナリであると確信している限り、バイナリへの正確なパスを使用しても何も失われません。


のスポットpython。私は場所の数のカウント失ってしまったpython😀見つけることができます
ziggの

2
ことで合意した/usr/bin/envあなたはvirtualenvのを使用する場合は特に、Python用より有用です。
デニス

10

/binほんの数例を挙げると、Bash in 、FreeBSD、OpenBSD がないシステムはたくさんあります。スクリプトが多くの異なるUnicesに移植できるように意図されている場合は、の#!/usr/bin/env bash代わりに使用することができます#!/bin/bash

これはには当てはまらないことに注意してくださいsh。Bourne準拠のスクリプトの場合は#!/bin/sh、私が独占的に使用shしてい/binます。これは、存在するほとんどすべてのUnixにがあると思います。


Ubuntuの18.04で/binDIR、私は見ますsh -> dash。に象徴的にリンクされdash、UbuntuのDebianの性質を明らかにします。それがすべての個々の好みに帰着実現するために、これらの3つのコマンド文字列を実行します。which bashそしてwhich sh、その後which dash
noobninja

0

メインプログラムを以下のようなスクリプトでラップして、bashシステムで利用可能なすべてをチェックすることをお勧めします。使用するバージョンをより詳細に制御した方がよい。

#! /usr/bin/env bash

# This script just chooses the appropriate bash
# installed in system and executes testcode.main

readonly DESIRED_VERSION="5"

declare all_bash_installed_on_this_system
declare bash

if [ "${BASH_VERSINFO}" -ne "${DESIRED_VERSION}" ]
then
    found=0

    all_bash_installed_on_this_system="$(\
        awk -F'/' '$NF == "bash"{print}' "/etc/shells"\
        )"

    for bash in $all_bash_installed_on_this_system
    do
        versinfo="$( $bash -c 'echo ${BASH_VERSINFO}' )"
        [ "${versinfo}" -eq "${DESIRED_VERSION}" ] && { found=1 ; break;}
    done
    if [ "${found}" -ne 1 ]
    then
        echo "${DESIRED_VERSION} not available"
        exit 1
    fi
fi

$bash main_program "$@"

0
 #!/usr/bin/env bash

システム環境変数からbash実行可能パスを見つけるため、間違いなく優れています。

Linuxシェルに移動して、次のように入力します。

env

すべての環境変数を出力します。

シェルスクリプトに移動して、次のように入力します。

echo $BASH

スクリプトで正しいシバンパスを構築するために使用する必要があるbashパスを(環境変数リストに従って)出力します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.