Sco*_*e T 385 linux script bash
执行像 A 这样的 Bash 脚本和采购像 B 这样的 Bash 脚本有什么区别?
A
> ./myscript
B
> source myscript
Run Code Online (Sandbox Code Playgroud)
les*_*ana 484
获取和执行脚本都将逐行运行脚本中的命令,就像您逐行手动键入这些命令一样。
区别在于:
“环境”是诸如当前工作目录和环境变量之类的东西。还有外壳设置(以及其他历史和完成功能)。还有更多,但那些是最明显的。
如果您希望脚本更改当前运行的 shell 中的环境,请使用 source。否则使用执行。
如果您想了解更多详情,请继续阅读。
澄清一些关于执行语法和源语法的常见混淆。
要执行的语法:
./myscript
Run Code Online (Sandbox Code Playgroud)
如果文件是可执行的并且位于当前目录中,这将执行 myscript。前导点和斜线 ( ./) 表示当前目录。这是必要的,因为当前目录通常不在(通常不应该)在$PATH.
myscript
Run Code Online (Sandbox Code Playgroud)
这将执行 myscript,如果该文件是可执行文件,位于某些目录$PATH。
源语法:
source myscript
Run Code Online (Sandbox Code Playgroud)
这将来源 myscript. 该文件不需要是可执行的,但它必须是有效的 shell 脚本。该文件可以在当前目录中,也可以在$PATH.
. myscript
Run Code Online (Sandbox Code Playgroud)
这也将来源 myscript. 这种“拼写”是POSIX定义的官方拼写。Bash 定义source为点的别名。
为了完整性:
exec myscript
Run Code Online (Sandbox Code Playgroud)
这将终止当前的 shell,然后执行 myscript 代替终止的 shell。这意味着当 myscript 完成时,没有外壳可以返回。exec功能强大但很少需要。
我在最后放了一些链接,以获取有关这些主题的更多信息。
考虑myscript.sh以下内容:
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
Run Code Online (Sandbox Code Playgroud)
在我们首先执行脚本之前,我们检查当前环境:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Run Code Online (Sandbox Code Playgroud)
变量FOO未定义,我们位于主目录中。
现在我们执行文件:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Run Code Online (Sandbox Code Playgroud)
再次检查环境:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Run Code Online (Sandbox Code Playgroud)
变量FOO未设置且工作目录未更改。
脚本输出清楚地显示变量已设置且目录已更改。之后的检查显示变量未设置且目录未更改。发生了什么?这些更改是在一个新的shell 中进行的。
在当前shell产生一个新的shell来运行该脚本。脚本在新 shell 中运行,对环境的所有更改都在新 shell 中生效。脚本完成后,新的外壳被销毁。对新 shell 中环境的所有更改都将随新 shell 一起销毁。在当前 shell 中仅打印输出文本。
现在我们源文件:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Run Code Online (Sandbox Code Playgroud)
再次检查环境:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
Run Code Online (Sandbox Code Playgroud)
变量 FOO 已设置,工作目录已更改。
采购脚本不会创建新的 shell。所有命令都在当前 shell 中运行,对环境的更改在当前 shell 中生效。
请注意,在这个简单示例中,执行的输出与获取脚本的输出相同。情况并非总是如此。
考虑以下脚本pid.sh:
#!/bin/sh
echo $$
Run Code Online (Sandbox Code Playgroud)
(特殊变量$$扩展为当前运行的shell进程的PID)
首先打印当前shell的PID:
$ echo $$
25009
Run Code Online (Sandbox Code Playgroud)
源脚本:
$ source pid.sh
25009
Run Code Online (Sandbox Code Playgroud)
执行脚本,注意PID:
$ ./pid.sh
25011
Run Code Online (Sandbox Code Playgroud)
再次来源:
$ source pid.sh
25009
Run Code Online (Sandbox Code Playgroud)
再次执行:
$ ./pid.sh
25013
Run Code Online (Sandbox Code Playgroud)
您可以看到采购脚本在同一进程中运行,而每次执行脚本都会创建一个新进程。该新进程是为执行脚本而创建的新shell。获取脚本不会创建新的 shell,因此 PID 保持不变。
采购脚本将运行当前shell 进程中的命令。对环境的更改在当前 shell 中生效。
执行脚本将在新的shell 进程中运行命令。对环境的更改在新 shell 中生效,并在脚本完成并终止新 shell 时丢失。
如果您希望脚本更改当前运行的 shell 中的环境,请使用 source。否则使用执行。
也可以看看:
小智 26
执行脚本会在单独的子进程中运行它,即调用单独的 shell 实例来处理脚本。这意味着无法在父(当前)shell 中更新脚本中定义的任何环境变量等。
获取脚本意味着它由当前 shell 本身解析和执行。就好像您键入了脚本的内容一样。出于这个原因,源脚本不需要是可执行的。但是,如果您当然要执行它,它必须是可执行的。
如果您在当前 shell 中有位置参数,它们将保持不变。
因此,如果我有一个a.sh包含以下内容的文件:
echo a $*
Run Code Online (Sandbox Code Playgroud)
我这样做:
$ set `date`
$ source ./a.sh
Run Code Online (Sandbox Code Playgroud)
我得到类似的东西:
a Fri Dec 11 07:34:17 PST 2009
Run Code Online (Sandbox Code Playgroud)
然而:
$ set `date`
$ ./a.sh
Run Code Online (Sandbox Code Playgroud)
给我:
a
Run Code Online (Sandbox Code Playgroud)
希望有帮助。
小智 9
除了上述之外,执行脚本./myscript需要文件 myscript 的执行权限,而采购不需要任何执行权限。这就是为什么chmod +x myscript不需要之前source myscript
| 归档时间: |
|
| 查看次数: |
180551 次 |
| 最近记录: |