2009-12-11 15:24:17 +0000 2009-12-11 15:24:17 +0000
302
302

执行Bash脚本与采购脚本的区别是什么?

执行像A这样的Bash脚本和采购像B这样的Bash脚本有什么区别?

A
> ./myscript

B
> source myscript

答案 (6)

369
369
369
2010-08-16 21:58:48 +0000

执行脚本将在当前的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,在新的shell中键入命令,把输出复制回当前的shell,然后关闭新的shell。任何对环境的改变将只在新的shell中生效,一旦关闭新的shell,这些改变就会丢失。
  • 当你source脚本时,你是在你的currentshell中输入命令。任何对环境的改变都会在你当前的shell中生效。

如果你想让脚本在你当前运行的shell中改变环境,请使用source,否则请使用execute。


也请参考。

23
23
23
2009-12-11 15:35:56 +0000

执行一个脚本会在一个单独的子进程中运行,也就是说,会调用一个单独的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

希望能帮到你。

9
9
9
2009-12-11 15:27:08 +0000

源码基本上就像在命令提示符下逐行输入脚本一样……

执行启动一个新的进程,然后运行每一行脚本,只通过返回的内容修改当前环境。

6
6
6
2012-02-23 07:27:43 +0000

除了上述情况,以./myscript的方式执行脚本需要文件myscript的执行权限,而sourcing则不需要任何执行权限。这就是为什么在chmod +x myscript之前不需要source myscript的原因。

5
5
5
2009-12-11 15:25:38 +0000

源码你可以得到所有在脚本中定义的额外变量。
所以如果你有配置或函数定义,你应该源码而不是执行。执行是独立于父环境的。

2
2
2
2015-03-27 14:04:20 +0000

source命令在当前的shell环境中执行所提供的脚本(可执行权限不是强制),而./新的shell中执行所提供的可执行脚本。

另外,可以看看这个答案的例子。https://superuser.com/a/894748/432100