クリーンな環境でスクリプトを開始する方法は?


15

私は以下を試しましたが、うまくいかないようです:

$ cat script.sh
#!/bin/env -i /bin/sh

/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.

同様の質問が見つかりましたがシェバングから行う方法を示していない:unix.stackexchange.com/questions/48994/...
balki

5
シバンからはできません。shebangは1つの引数のみを受け入れることができます。
ヨルダン

回答:


7

これが機能しない理由は-i /bin/sh、に対する単一の引数と見なされるためenvです。通常、これは2つの引数に-iなり/bin/shます。これは、シバンの制限です。それを回避する方法はありません。


ただし、別の方法でこのタスクを実行できます。

このタスクをスクリプト自体によって実行し、のような何かenv -i script.shをする必要がない場合は、スクリプト自体を再実行させることができます。

#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"

これにより、CLEANED環境変数が設定されていない場合、スクリプトはそれ自体を再実行します。次に、再実行時に変数を設定して、ループに陥らないようにします。


env現在、GNU coreutilsには、-Sこれと同様の問題を回避するオプションがありますが、まったく同じではありません。たとえば#!/usr/bin/env -S perl -T
ウェイジュン周

試しました。元の質問にも機能します。使用するだけ#!/usr/bin/env -S -i /bin/shです。移植性の問題に注意してください。
ウェイジュン周

3

以下を使用してスクリプトを実行しますenv -i

env -i script.sh

そして、いつものスクリプト:

#!/bin/sh
# ... your code here

実行時に明示的に言うことなく、クリーンな環境で実行するつもりである場合。Eduardo Ivanecはこの回答でいくつかのアイデアを提供execしています。環境がクリーンでない場合(たとえば$ HOMEが定義されている場合)にスクリプトを再帰的に呼び出すことができます。

[ "$HOME" != "" ] && exec -c $0

いいね ちょうど私がやったようにenv -i bashをしないで、なぜあなたのenv変数がまだ設定されているのか疑問に思う(もちろんbashリソース.bashrcと友人8)
ニールマクギル

2

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設定。

HOMEbashは非インタラクティブモードでスクリプトを実行するため、変数のテストは安全である必要があります。つまり、~/.bashrc(環境変数が設定される可能性がある)構成ファイルは起動時に取得されません。

出力例:

declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"

0

$ cat script.sh

#!/bin/env -i /bin/sh

残念ながら、その方法では動作しません。Linuxは-i /bin/sh、渡される引数の1つと見なしますenvShebangを参照)。


0

Linuxの2引数シバン制限(インターペッター+単一引数)はほとんどの回答に記載されていますが、これを行うことができないと言うのは間違っています。

#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here

これが行うことは、引数を正しくクォートして、をクリア()し、呼び出すperl1ライナースクリプト(-e)で呼び出します。必要に応じて、さらにロジックを追加できます(ただし、Linuxではそれほど多くはありませんが、文字に制限されているため、おそらく128です)。%ENVenv -iexec /bin/shperlBINPRM_BUF_SIZE

悲しいことに、これはLinux固有であり、複数のシバン引数を許可するシステムでは動作しません:-/

perlこの文字列を単一の引数として処理するため、通常はコマンドラインから行うように上に引用符で囲まれていませんperl -e ...絶え間ない)。

また、動作のわずかな変化この方法を使用する場合、あります注意して@ARGV正常に引数のみが含まれており、$0スクリプトが含まれていますが、このシェバングと$ARGV[0]スクリプトの名前である(と$0され-e、それが少し楽になります)。

-c古代のAT&T ksh93が行うコマンドライン(余分な引数なし)を「再処理」するインタープリターでこれを解決することもできます。

#!/bin/ksh /usr/bin/env -i /bin/sh

おそらくksh最近ではそれほど一般的ではないかもしれませんが、;-)

bashと同様の機能を持って--wordexpしかし、それはそれが動作し、それが文書化されたバージョンでは、コンパイル時に有効になっていないバージョンでは、「文書化されていない」だ-それは二つの引数を必要とするので、/また、このために使用することはできません。 ..)

また、@ Patrickと@maxschlepzigの回答の効果的なバリエーション:

#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here

むしろ使用より新たな変数が、これは特別な「使用_bashの」それは正確に設定されていない場合は、変数を「」その後でスクリプトを置き換えるexec使用して-a作成するARGV[0](したがって$_)単に「bashの」、および使用-c環境をクリアします。

または、スクリプトの開始時に環境をクリーニングしても問題ない場合(bashのみ):

#!/bin/sh
unset $(compgen -e)
# your script here

これはcompgen(補完ヘルパー)を使用して、エクスポートされたすべての環境変数の名前をリストし、unsetそれらを一度に実行します。

シバング行動の一般的な問題の詳細については、シバングの複数の引数も参照してください。

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