web-dev-qa-db-ja.com

任意のシェルで実行されるシェルスクリプトの記述(複数のシバン行を使用していますか?)

私はシェルスクリプトの詳細を学び始めたばかりで、常にスクリプトをファイルに入れてchmod +xとマークし、次に/path/to/script.shを実行して、デフォルトのインタープリターにデフォルトの方法を使用させていますそれは私がzshであると私が想定したもので、それは私が自分のシェルに使用したものだからです。どうやら、zshプロンプトからスクリプトを実行したとしても、スクリプトにzsh固有のものを入れ始めたので、/bin/shを実行しないと失敗するため、デフォルトではzsh /path/to/script.shだけのようです。

ポイントを得るために、ここに私の質問があります:

  1. 最初にシバン行(#!/path/to/Shell)がない場合、どのシェルがスクリプトを実行しますか? /bin/shと思いますが、確認できません。
  2. 任意のプラットフォームで実行されるシェルスクリプトを作成するという観点から、「ベストプラクティス」と見なされるものは何ですか? (OK、これは一種の自由回答です)
  3. Zshを使用しようとし、zshが使用できない場合にbashにフォールバックするスクリプトを作成することは可能ですか?以下のように2つのシバン行を入れてみましたが、zshのないマシンで試した場合、bad interpreter: /bin/zsh: no such file or directoryでエラーになります。

    #!/bin/zsh

    #!/bin/bash

19
swrobel

最初にシバン行(#!/ path/to/Shell)がない場合、どのシェルがスクリプトを実行しますか?/bin/shを想定していますが、確認できません。

カーネルはそのようなスクリプトの実行を拒否し、ENOEXECを返すため、正確な動作は、そのようなスクリプトfromを実行するプログラムによって異なります。

  • bash 4.2.39 –それ自体を使用します
  • busybox-ash 1.20.2 –自身を使用します
  • ダッシュ0.5.7 –/bin/shを実行します
  • fish 1.23.1 – ENOEXECについて文句を言い、間違ったファイルを非難する
  • AT&T ksh 93u + 2012.08.01 –自身を使用
  • mksh R40f –/bin/shを実行します
  • pdksh 5.2.14 –/bin/shを実行します
  • sh-heirloom 050706 –それ自体を使用します
  • tcsh 6.18.01 –/bin/shを実行します
  • zsh 5.0.0 –/bin/shを実行します
  • cmd.exe 5.1.2600 –あなたを面白く見ます。

glibcでは、関数execv()またはexecve()はENOEXECを返すだけです。ただし、execvp()はこのエラーコードを非表示にし、/ bin/shを自動的に呼び出します。 (これは exec(3p) に記載されています。)

任意のプラットフォームで実行されるシェルスクリプトを作成するという観点から、「ベストプラクティス」と見なされるものは何ですか? (OK、これは一種の自由回答です)

shとPOSIX定義の機能のみに固執するか、またはbash(広く利用可能)をフルにして、配布する場合は要件に記載してください。

(今考えてみると、Perl –またはおそらくPython –は、構文が優れていることは言うまでもなく、さらに移植性が高いでしょう。)

常にシバンラインを追加します。 bashまたはzshを使用する場合は、シェルのパスをハードコーディングする代わりに#!/usr/bin/env bashを使用します。 (ただし、POSIXシェルは/bin/shにあることが保証されているため、その場合はenvをスキップしてください。)

(残念ながら、/bin/shでさえ常に同じであるとは限りません。GNUautoconfプログラムは 多くの異なる癖 。)

Zshを使用しようとし、zshが使用できない場合にbashにフォールバックするスクリプトを作成することは可能ですか?以下のように2つのシバン行を入れてみましたが、悪いインタープリターでエラーが発生しました:/ bin/zsh:そのようなファイルやディレクトリはありませんマシンで試した場合zshなし。

シバンラインは1つしか存在できません。改行文字の後のすべてはカーネルによっても読み取られず、シェルによってコメントとして扱われます。

#!/bin/shとして実行され、使用可能なシェルを確認し、結果に応じてexec zsh "$0" "$@"またはexec bash "$0" "$@"を実行するスクリプトを作成することは可能です。 。ただし、bashとzshで使用される構文はさまざまな場所で非常に異なるため、自分の正気のためにこれを行うことはお勧めしません。

27
user1686

1)実行している現在のシェル。

2)同じシェルタイプ(bash/dash/ash/csh /どのフレーバーでも)を使用し、「サポートされているプラ​​ットフォーム」がデフォルトで使用するシェルをインストールしていることを確認します。また、システムで一般的に使用可能なコマンドを使用してみてください。マシン固有のオプションは避けてください。

3)interpreter directiveには実際には「if-then-else」ロジックはありません。サポートするすべてのシステムに存在する必要があるシェルを指定する必要があります...つまり、スクリプトがすべてのシェルでかなり汎用的である限り、#!/bin/bashまたは汎用の#!/bin/shを指定します。

2
TheCompWiz