私は以下を試しましたが、うまくいかないようです:
$ cat script.sh
#!/bin/env -i /bin/sh
/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.
私は以下を試しましたが、うまくいかないようです:
$ 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
です。通常、これは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
です。移植性の問題に注意してください。
以下を使用してスクリプトを実行しますenv -i
。
env -i script.sh
そして、いつものスクリプト:
#!/bin/sh
# ... your code here
実行時に明示的に言うことなく、クリーンな環境で実行するつもりである場合。Eduardo Ivanecはこの回答でいくつかのアイデアを提供exec
しています。環境がクリーンでない場合(たとえば$ HOMEが定義されている場合)にスクリプトを再帰的に呼び出すことができます。
[ "$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"
Linuxの2引数シバン制限(インターペッター+単一引数)はほとんどの回答に記載されていますが、これを行うことができないと言うのは間違っています。
#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here
これが行うことは、引数を正しくクォートして、をクリア()し、呼び出すperl
1ライナースクリプト(-e
)で呼び出します。必要に応じて、さらにロジックを追加できます(ただし、Linuxではそれほど多くはありませんが、文字に制限されているため、おそらく128です)。%ENV
env -i
exec /bin/sh
perl
BINPRM_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
それらを一度に実行します。
シバング行動の一般的な問題の詳細については、シバングの複数の引数も参照してください。