web-dev-qa-db-ja.com

同じスクリプトを3つの異なる方法で開くと、3つの異なる結果が生成されます。どうして?

サンプルスクリプトがあります(クレジットは kos に移動します):

#!/bin/bash
cat <(cat /etc/lsb-release)

このスクリプトをホームディレクトリにsomename.shとして保存します。

次に、このファイルを3つの異なる方法で開こうとします。

sh somename.sh

bash somename.sh

./somename.sh

したがって、2つの質問があります。

  1. 同じスクリプトを実行しているにもかかわらず、上記のコマンドの出力が異なるのはなぜですか?

    • shは構文エラーを生成します

    • bashは望ましい結果を出力します

    • ./Permission Deniedエラーが発生します

  2. ./を使用してスクリプトを実行する場合にのみスクリプトに実行許可を与える必要があり、他の場合には必要ないのはなぜですか?

前もって感謝します!

EDIT:最初の部分は duplicate リンクされた部分に似ているかもしれませんが、2番目の質問もありました。

7
Raphael

チャットで説明したように:

  1. インタプリタ(この場合はsh)を直接呼び出すとシバンが無視され、スクリプトはshで実行されるため、sh scriptはエラーを生成します。 shは、Bash-ismであるプロセス置換(<([...]))をサポートしていないため、スクリプトはエラーで終了します。

    bash scriptはエラーを生成しません。Shebangは無視されますが、スクリプトはまだプロセス置換をサポートするBashで実行されているためです。

    scriptは実行可能でないため、./scriptはエラーを生成します。

  2. ./を使用してスクリプトを実行するには、mustにユーザーの実行ビットを設定する必要があります。これはOSの制約です。

    したがって、実際の質問は次のとおりです。なぜbash scriptscriptのユーザーに実行ビットを設定する必要がないのですか?

    これは、bash scriptの実行時にスクリプトがBashによって読み取られ、Bashhasがユーザーに設定された実行ビットであるためです。

    つまり、コードを実行する権限を持つBashは、そのスクリプトに対するOSの制約を「バイパス」でき、スクリプトに必要なものはすべてBashで読み取り可能になるということです。

8
kos
  • shdash Shellへのシンボリックリンクであり、sh構文には<( . . .)がないため、構文エラーが生成されます。それはbashにのみあります(正しく覚えていればzshkshにあります)。

  • bashは正しいbash構文であるため、目的の結果を出力します。

  • ./は、基本的に「おい、シェル、そのファイルのパーミッションを見て、私の現在のディレクトリの最初の行(#!/bin/bashが付いているもの)を見て、このスクリプトを実行する方法を見つけてください」。 (サイドノート:$PATH変数に含まれる場所にスクリプトがある場合は、myScriptName.shを実行するだけです。それでも同じです。考えは同じです。execを確認する必要があります。許可と使用するインタープリター)

bashおよびdashを実行して、ファイルからコマンドを読み取るように指示する前。 bashdashは、スクリプトではなく今回実行可能です。スクリプトは現在、コマンドのソース、パラメーターです。読み取り権限は常にすべてのユーザーに設定されているため、シェルはそれを読み取ります。

5

一般的にshashdashbashcshtcshzsh...はすべてシェルです。独自の構文と特性。いくつかの互換性がありますが、それらはorientedです [ 1 ]bashシェルはshスクリプトを実行しますが、viceversaとは言われていません。 shの呼び出しは、bashの呼び出しよりも少ないリソースで済みます。単一のインスタンスでは問題になりませんが、数千では問題になります。

実行方法。
Linuxでファイルをプログラムとして実行するには、スクリプトまたはコンパイルされたファイルの両方である場合、execute bitを設定する必要があります。 [ 2 ] また、$PATHのいずれかのディレクトリに含める必要があります。

スクリプトの場合、相対シェルに引数として渡すことができます(shbash...myfile.whatever):間違ったシェルに渡される場合正しくない動作を取得し、エラーがラッキーだった場合;この場合は実行可能である必要はありませんスクリプト内に直接記述された行を記述する場合と同じように新しいシェルで呼び出します。同じシェルで代わりに実行するには、現在のシェルで行ごとにを記述するのと同等のsource myfileまたは. myfileを使用できますスクリプトのコンテンツ。

場所
実行可能プログラムがパスに含まれていない場合は、それがどこにあるかを指定する必要があります。

  • あなたの場合、./はシェルの現在のディレクトリのみを意味します。また、~/myfile.whateverはホームのmyfile.whateverディレクトリにあるファイル~/を指定する必要があります。
  • /home/$USER/dir/myfile.whateverなどを使用して、別の場所から呼び出すことができます。
  • このファイルがパスに含まれるディレクトリ内にある場合は、単純なmyfile.whateverで呼び出すことができます。

複数の実行可能ファイルが同じ名前を共有している場合、フルパスを指定すると、実行する実行可能ファイルについて確実になります。 which mycommandは、現在実行されているもの(関数、エイリアス、組み込み、またはパスで最初に検出されたもの)を通知できますが、将来実行されるか、または別のユーザーから実行されるかはわかりません。完全なパスを明示的に記述した場合、このあいまいさは修正されます。特定のバージョンのプログラムを同時に複数インストールした場合に実行し、トロイの木馬を回避すると便利です。スクリプトでは、bashの代わりに_/bin/bashを記述することが常に推奨されます。

3
Hastur