#!/usr/bin/env bash
スクリプトは通常、実行に使用するシェルを指定するshebangで始まります。 shebangが存在しない場合の実行動作は次のとおりです。シェルが呼び出されるまで。いずれにしても、スクリプトは、シェルで定義された変数と関数を呼び出す方法がわからない「新しい」シェルで実行されます。
あるいは、source
スクリプトをシェルに入れることもできます。これは、スクリプトの内容を現在のシェルにコピーして貼り付けるのと同じです。関数または変数がスクリプトで定義されている場合は、「実行」後も呼び出しシェルに残るため、望ましくない可能性があります。
これら2つのオプションの間に関係がありますか?スクリプトを呼び出しシェルのサブシェルとして実行して、呼び出しシェルで定義されているすべてのエントリにアクセスできますが、変更しないようにすることはできますか(export
そのようなコマンドを使用しない限り)。
執筆は(source myscript.sh)
私が求めているようだった。それが正しいことでしたか?同じ動作を生成するために呼び出すことができる同等のshebangはありますか./myscript.sh
?
答え1
(. ./myscript.sh)
正しい方法です(標準型は.
、ではないsource
、).
で指定されたディレクトリは検索されませんPATH
。
shebangを使用してこれを行うには、親スクリプトを実行しているシェルのバイナリを見つけるための安定した方法が必要です。いいえ環境変数によって異なります。 Linuxでは、/proc/parent
次のことを想像できます。/proc/self
、親プロセスを指すと書くことができます。
#! /proc/parent/exe -
シェルスクリプトが親プロセスが実行されているバイナリを使用するようにします。 (これは元のシェルが削除または置き換えられても機能し、/proc/self/exe
バイナリが削除されても動作し、/proc/parent/exe
同じ方法で実行されます。)しかし、スクリプト自体を実行するために盲目的に親プロセスのバイナリに依存することは信頼できません(親プロセスは子プロセスが始まると死んで競争が発生します)。
答え2
POSIX(IEEE規格1003.1-2017、セクション2.12)指定:
サブシェル環境は、シェル環境のコピーとして作成する必要があります。ただし、無視されないシグナルトラップはデフォルトジョブに設定する必要があります。サブシェル環境への変更は、シェル環境に影響を与えてはいけません。。
したがって、サブシェルが呼び出しシェルのすべてにアクセスできることは正しいですが、親export
シェルの環境を変更できるようなコマンドについては間違っていました。
もちろん、POSIXは次のように書式を設定します。
( compound-list )
Execute compound-list in a subshell environment; ...
./myscript.shを呼び出して同じ動作を生成する同等のshebangはありますか?
スクリプトにshebangがあるとしましょう。指定したインタプリタ(bashなど)を使用して実行されますが、次のように実行されます。別のプロセス、よりサブシェル。ただし、これにより、親シェル環境を変更しないスクリプトを実行することで、望ましい結果が得られます。
$ cat script.sh
#!/usr/bin/env bash
VAR=modified
echo "VAR is $VAR"
echo "PID: $$"
$ echo "Parent: $$"
Parent: 793915
$ VAR=initial
$ ./script.sh
VAR is modified
PID: 799149
$ echo $VAR
initial
$ bash script.sh
VAR is modified
PID: 799784
$ echo $VAR
initial
$ . script.sh
VAR is modified
PID: 793915
$ echo $VAR
modified
注: 点.
コマンドはsource
。
修正するset -a
:対応するオプションを設定しないと、スクリプトとして実行すると環境変数がエクスポートされないことを忘れていました。しかし、割り当てられた変数だけを覚えておいてください。後ろにこのオプションをオンにするとエクスポートされます。これが望んでいない場合は、最良の選択は次のとおりです。(. script.sh)
マニュアルから:
-a
このオプションが有効になっている場合は、割り当てを実行する各変数にエクスポートプロパティを設定する必要があります。
$ cat script.sh
#!/usr/bin/env bash
echo "VAR is $VAR"
VAR=modified
echo "VAR now set to $VAR"
$ VAR=original
$ (. script.sh)
VAR is original
VAR now set to modified
$ echo $VAR
original
$ # works as expected, unchanged
$ ./script.sh
VAR is
VAR now set to modified
$ # var not sent over
$ set -a
$ VAR=original
$ ./script.sh
VAR is original
VAR now set to modified
$ echo $VAR
original
$ # works, and your variable remains unchanged
$ set +a # turn the option off