执行脚本将在当前的shell进程中运行命令。
执行 脚本将在一个_新的shell进程中运行命令。
如果你想让脚本改变当前运行的shell的环境,请使用source,否则请使用execute。
如果你仍然感到困惑,请继续阅读。
为了澄清一些常见的关于execute和source语法的混淆:
./myscript
这将执行 myscript
,前提是文件是可执行的,并且位于当前目录。前面的点和斜线 (./
) 表示当前目录。这是必要的,因为当前目录通常不在(通常也不应该在)$PATH
中。
myscript
如果文件是可执行的,并且位于myscript
的某个目录中,这将执行$PATH
。
source myscript
这将源 myscript
。文件不必是可执行文件,但必须是有效的 shell 脚本。文件可以在当前目录下,也可以在$PATH
的目录下。
. myscript
这也将source myscript
。这个 “拼法 "是官方定义的 POSIX 。Bash将source
定义为点的别名。
考虑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
在执行脚本之前,我们首先检查当前的环境。
$ env | grep FOO
$ echo $PWD
/home/lesmana
变量FOO
没有定义,我们在主目录下。
现在我们执行文件。
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
再次检查环境:
$ env | grep FOO
$ echo $PWD
/home/lesmana
变量FOO
没有设置,工作目录也没有改变。
脚本输出清楚地显示,变量已被设置,目录已被改变。之后的检查显示,变量没有设置,目录也没有改变。到底发生了什么?修改是在一个新的shell中进行的。当前的 shell 生成了一个 new shell 来运行脚本。脚本在新的 shell 中运行,所有对环境的改变在新的 shell 中生效。脚本完成后,新shell被销毁。所有在新shell中对环境的修改都会随着新shell一起销毁。只有输出的文本在当前shell中被打印出来。
现在我们source文件。
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
再次检查环境:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
变量FOO已经设置,工作目录已经改变。
Sourcing脚本不会创建一个新的shell。所有的命令都会在当前shell中运行,对环境的改变也会在当前shell中生效。
请注意,在这个简单的例子中,执行的输出与source脚本的输出是一样的。但这不一定总是如此。
考虑以下脚本 pid.sh
:
#!/bin/sh
echo $$
(特殊变量$$
扩展为当前运行的shell进程的PID)
首先打印当前shell的PID:
$ echo $$
25009
源脚本。
$ source pid.sh
25009
执行脚本,注意PID:
$ ./pid.sh
25011
再次源:
$ source pid.sh
25009
再次执行:
$ ./pid.sh
25013
你可以看到,源脚本在同一个进程中运行,而执行脚本每次都创建一个新的进程。这个新进程就是为执行脚本而创建的new shell。采购脚本不会创建一个新的shell,因此PID保持不变。
采购和执行脚本都会逐行运行脚本中的命令,就像你逐行手工输入这些命令一样。
不同之处在于。
如果你想让脚本在你当前运行的shell中改变环境,请使用source,否则请使用execute。
也请参考。
执行一个脚本会在一个单独的子进程中运行,也就是说,会调用一个单独的shell实例来处理这个脚本。这意味着在脚本中定义的任何环境变量等不能在父进程(当前)shell中更新。
Sourcing一个脚本意味着它被当前shell本身解析和执行。就像你输入了脚本的内容一样。因此,被外包的脚本不需要是可执行的。但如果你要执行它,当然必须是可执行的。
如果你在当前shell中拥有位置参数,它们是不变的。
所以,如果我有一个文件a.sh
包含:
echo a $*
而我这样做。
$ set `date`
$ source ./a.sh
我得到的是这样的结果。
a Fri Dec 11 07:34:17 PST 2009
而我的操作是:
$ set `date`
$ ./a.sh
得到:
a
希望能帮到你。
源码基本上就像在命令提示符下逐行输入脚本一样……
执行启动一个新的进程,然后运行每一行脚本,只通过返回的内容修改当前环境。
源码你可以得到所有在脚本中定义的额外变量。
所以如果你有配置或函数定义,你应该源码而不是执行。执行是独立于父环境的。
source
命令在当前的shell环境中执行所提供的脚本(可执行权限不是强制),而./
在新的shell中执行所提供的可执行脚本。
另外,可以看看这个答案的例子。https://superuser.com/a/894748/432100