web-dev-qa-db-ja.com

クリーンな環境でスクリプトを開始するにはどうすればよいですか?

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

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

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

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


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

このタスクをスクリプト自体で実行し、env -i script.shなどを実行する必要がない場合は、スクリプト自体を再実行することができます。

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

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

7
Patrick

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

env -i script.sh

そしていつものようにスクリプト:

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

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

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

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"
2
maxschlepzig

$ cat script.sh

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

残念ながら、この方法では機能しません— Linuxは-i /bin/shenvに渡される1つの引数と見なします( Shebang を参照)。

0
poige

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(補完ヘルパー)を使用して、エクスポートされたすべての環境変数の名前をリストし、それらを一度にunsetsします。

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

0
mr.spuratic