执行 Bash 脚本与采购它有什么区别?

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,在新的shell 中键入命令,将输出复制回当前的 shell,然后关闭新的 shell。对环境的任何更改仅在新 shell 中生效,并且在新 shell 关闭后将丢失。
  • 当你采购你在你键入的命令脚本目前的外壳。对环境的任何更改都将生效并保留在您当前的 shell 中。

“环境”是诸如当前工作目录和环境变量之类的东西。还有外壳设置(以及其他历史和完成功能)。还有更多,但那些是最明显的。

如果您希望脚本更改当前运行的 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。否则使用执行。


也可以看看:

  • source 的一个用途是为您的脚本创建一个基本形式的配置文件。您首先将各种变量设置为默认值,然后在 myscript.conf 之类的内容中获取源代码 - 并且该源脚本可以具有覆盖您想要的任何值的赋值语句。由于源脚本不是以#/bin/bash 开头,因此不鼓励直接执行它。 (6认同)
  • 使用 `source myscript.sh` 和 `. myscript.sh`? (5认同)
  • 我喜欢人们提供如此详尽的示例,以便即使像我这样的 Linux 新手也能理解。谢谢! (5认同)
  • 如果使用 bash,几乎没有区别。source 是 bash 中 dot 的别名。 (4认同)

小智 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认同)

Joh*_*don 9

采购本质上与在命令提示符下一次键入脚本的每一行相同...

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


小智 9

除了上述之外,执行脚本./myscript需要文件 myscript 的执行权限,而采购不需要任何执行权限。这就是为什么chmod +x myscript不需要之前source myscript

  • 没错,但如果这是一个问题,您可以随时运行`bash myscript`。 (3认同)

小智 5

采购您可以获得脚本中定义的所有额外变量。
因此,如果您有配置或函数定义,则应该获取而不是执行。执行独立于父环境。