私は以下を試しましたが、うまくいかないようです:
$ cat script.sh
#!/bin/env -i /bin/sh
/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.
これが機能しない理由は、-i /bin/sh
がenv
への単一の引数として認識されるためです。通常、これは-i
と/bin/sh
の2つの引数になります。これはシバンの制限です。それを回避する方法はありません。
ただし、このタスクは別の方法で実行できます。
このタスクをスクリプト自体で実行し、env -i script.sh
などを実行する必要がない場合は、スクリプト自体を再実行することができます。
#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"
これにより、CLEANED
環境変数が設定されていない場合に、スクリプト自体が再実行されます。次に、再実行時に、変数を設定してループに入らないようにします。
env -i
を使用してスクリプトを実行します。
env -i script.sh
そしていつものようにスクリプト:
#!/bin/sh
# ... your code here
クリーンな環境で実行するつもりなら、実行時にそれを明示的に言うことはありません。 Eduardo Ivanecは この答え でいくつかのアイデアを提供しています。環境がクリーンでない場合($ HOMEが定義されている場合など)は、exec
を使用してスクリプトを再帰的に呼び出すことができます。
[ "$HOME" != "" ] && exec -c $0
Bashを使用すると、次のように実行できます。
#!/usr/bin/bash
set -e
set -u
[ -v HOME ] && exec -c "$0" "$@"
# continue with the rest of the script
# e.g. print the cleaned environment:
export
set -e
コマンドとset -u
コマンドは厳密には必要ありませんが、このアプローチは未設定の変数へのアクセスに依存せず(例:[ "$HOME" != "" ]
がそうする)と互換性があり、 set -e
設定。
HOME
変数のテストは、bashが非対話モードでスクリプトを実行するため、安全である必要があります。つまり、~/.bashrc
(環境変数が設定される可能性がある)などの構成ファイルは、起動時に読み込まれません。
出力例:
declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"
$ cat script.sh
#!/bin/env -i /bin/sh
残念ながら、この方法では機能しません— Linuxは-i /bin/sh
をenv
に渡される1つの引数と見なします( Shebang を参照)。
Linuxの2引数シバン制限(インターピーター+単一引数)はほとんどの回答で指摘されていますが、これを行うことができないと言うのは正しくありません。単一引数で役立つ何かを実行できるインタープリターに変更する必要があるだけです。
#!/usr/bin/Perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here
これは、-e
(%ENV
よりも安い)をクリアし、env -i
を呼び出すワンライナースクリプト(exec /bin/sh
)を使用してPerl
を呼び出し、正しく引用します。引数。必要に応じて、さらにPerl
ロジックを追加できます(ただし、LinuxではBINPRM_BUF_SIZE
文字に制限されているため、128文字であることが多いため)
悲しいことに、これはLinux固有であり、複数のシバン引数を許可するシステムでは機能しません:-/
Perl
はこの文字列を単一の引数として処理するため、通常はPerl -e ...
を使用して行うのと同じように、引用符で囲まれていません。コマンドライン(引用符を追加しようとした場合、これらは保持されます。Perlはリテラル文字列のみを認識し、警告が表示されて、役に立たない定数について文句を言います)。
また、この方法を使用すると動作に若干の変更があることに注意してください。通常、@ARGV
には引数のみが含まれ、$0
にはスクリプトが含まれますが、このシバンでは$ARGV[0]
がスクリプトの名前です( $0
は-e
)であり、少し簡単になります。
コマンドラインを "再処理"するインタプリタを使用してこれを解決することもできます(余分な-c
引数なしで)、古代のAT&T ksh93
は次のように処理します。
#!/bin/ksh /usr/bin/env -i /bin/sh
おそらくksh
は今日ほど一般的ではありません;-)
(bash
は--wordexp
と同様の機能を備えていますが、しかし機能するバージョンでは「ドキュメント化されていません」。文書化されているバージョンではコンパイル時に有効になります:-/ 2つの引数が必要なため、これにも使用できません...)
また、@ Patrickと@maxschlepzigの回答のバリエーションも効果的です。
#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here
新しい変数を使用するのではなく、特別な「_
」変数を使用します。正確に「bash」に設定されていない場合は、-a
を使用してスクリプトをexec
に置き換え、ARGV[0]
(したがって$_
)は単に「bash」し、-c
を使用して環境をクリアします。
または、スクリプトの開始時に環境をクリーンアップすることが許容される場合(bashのみ):
#!/bin/sh
unset $(compgen -e)
# your script here
これはcompgen
(補完ヘルパー)を使用して、エクスポートされたすべての環境変数の名前をリストし、それらを一度にunset
sします。
シバン動作の一般的な問題の詳細については、 シバンの複数の引数 も参照してください。