Shebangの複数のパラメータ

Shebangの複数のパラメータ

#!shebang line()を介して実行可能ファイルに複数のオプションを渡す一般的な方法があるかどうか疑問に思います。

私はNixOSを使用していますが、私が書いたすべてのスクリプトでshebangの最初の部分は一般的です/usr/bin/env。問題は、次のすべてがシステムによって単一のファイルまたはディレクトリとして解釈されることです。

bashたとえば、posixモードで実行されるスクリプトを作成するとします。 Shebangを書く簡単な方法は次のとおりです。

#!/usr/bin/env bash --posix

ただし、生成されたスクリプトを実行しようとすると、次のエラーが発生します。

/usr/bin/env: ‘bash --posix’: No such file or directory

わかりましたこの投稿しかし、より一般的でクリーンなソリューションがあるかどうかを知りたいです。


編集する:私も知ってるいたずらスクリプト、私が欲しいものを達成する方法があります。セクション4.3.4マニュアル:

 #!/usr/bin/env sh
 exec guile -l fact -e '(@ (fac) main)' -s "$0" "$@"
 !#

ここでの秘訣は、2 行目 ( but で始まる ) が code , ... ブロック内部の注釈execとして解釈されるので Guile ソルバーで無視されるということです。sh#!!#

このアプローチをすべての通訳者に一般化することはできませんか?


2番目の編集:いくつかの試みの後にstdin入力を読むことができるインタプリタについては、次のことがうまくいくようです。

#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;

shただし、通訳者が作業を完了するまでプロセスが続くため、これは最適ではない可能性があります。どんなフィードバックや提案にも感謝します。

答え1

完全に移植可能ではありませんが、coreutils 8.30からその文書によると以下を使用できます。

#!/usr/bin/env -S command arg1 arg2 ...

だから与えられた:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too

あなたは得るでしょう:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'

気になるならshowargs:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
    echo "\$$i is '$arg'"
    i=$((i+1))
done

答え2

少なくともLinuxをサポートする必要がある場合は、普遍的なソリューションはありません。Linuxカーネルは、shebang行の最初の「単語」以降のすべてのエントリを単一の引数として扱います。

NixOSの制限が何であるかはよくわかりませんが、一般的に私はあなたのshebangを次のように書いています。

#!/bin/bash --posix

または可能であれば、スクリプトでオプションを設定する:

set -o posix

あるいは、適切なシェル呼び出しを使用して、スクリプトを独自に再起動させることもできます。

#!/bin/sh -

if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "$@"; fi

shift

# Processing continues

ターゲット言語が最初の数行(シェルで解釈される)を無視する方法を見つける限り、このアプローチを他の言語に一般化できます。

GNU coreutils'envバージョン8.30以降、回避策を使用できます。ブラックノード~の回答もっと学ぶ。 (Debian 10以上、RHEL 8以上、Ubuntu 19.04以上などで使用できます。)

答え3

POSIX規格の説明は非常に簡潔です#!

~からexec()システムインタフェースシリーズ文書の基本原理部分:

いくつかの歴史的実装がシェルスクリプトを処理する別の方法は、ファイルの最初の2バイトを文字列として認識し、ファイルの最初の行の残りの#!部分を実行するコマンドソルバーの名前として使用することでした。

~からシェル紹介部:

シェルは、POSIX.1-2008システムインターフェースボリュームで定義されているファイル(参考資料を参照sh)、オプション、または関数から入力を読み取ります。-csystem()popen()シェルコマンドファイルの最初の行が文字で始まる場合、#!結果は指定されません。

これは、基本的に、すべての実装(使用しているUnix)が必要に応じてshebang行解析の詳細を自由に実行できることを意味します。

macOS(ATMをテストできない)などの一部のUnicesは、shebangラインでインタプリタに提供されたパラメータを別々のパラメータに分割しますが、Linuxおよび他のほとんどのUnicesはインタプリタにパラメータを単一のオプションとして提供します。

したがって、複数のパラメータを受け入れるためにshebang行に頼ることは賢明ではありません。

また見てくださいWikipedia Shebang 記事の移植性セクション


すべてのユーティリティや言語に一般化できる簡単な解決策は、適切なコマンドライン引数を使用して実際のスクリプトを実行するラッパースクリプトを作成することです。

#!/bin/sh
exec /bin/bash --posix /some/path/realscript "$@"

個人的にやり直そうとは思わない。それ自体少し虚弱な感じがするからです。

答え4

で説明されている shebangexecve(2)マニュアルページは次のとおりです。

#! interpreter [optional-arg]

この構文は2つのスペースを受け入れます。

  1. ハンカンの前に通訳パスですが、このスペースはオプションです。
  2. スペースで区切る通訳パスと対応するオプションのパラメータ。

オプションのパラメータについては、複数形を使用せず、上記の構文も使用しません[optional-arg ...]でした。最大1つのパラメータを提供できます。

シェルスクリプトの場合、setスクリプトの先頭付近に組み込みコマンドを使用できます。これにより、インタプリタパラメータを設定でき、コマンドラインパラメータを使用するのと同じ結果を得ることができます。

あなたの場合:

set -o posix

Bashプロンプトでhelp set利用可能なすべてのオプションの出力を確認します。

関連情報