“source x”,“有什么区别? Bash中的x“和”./x“?

我有一个bash源run.sh如下,

 #!/bin/bash if [ $# -ne 1 ]; then exit fi ... 

当我以两种方式执行它时,会有不同的行为。 第一种方式是,

 source run.sh 

它将在执行后关闭终端。 第二种方式是,

 ./run.sh 

这将简单地完成脚本运行,并留在终端上。 我问是否有一个命令退出source run.sh./run.sh执行的bash脚本。 我也尝试过return ,但在./run.sh执行下效果不佳。

更一般地说,我感兴趣的是为什么会发生这种情况,以及使用“source”和“。”之间的区别。 用于脚本执行?

在回答之前,我认为需要做出一些澄清。 我们来分析以下三行:

 source run.sh . run.sh ./run.sh 

前两行完全相同: . 实际上是source的别名。 什么source在当前上下文中执行shell脚本,因此对exit的调用将退出shell。

然而第三行(令你困惑的那一行)与其他行没有任何关系。 ./run.sh只是一个路径,与(例如) /home/user/run.sh/usr/bin/something 。 永远记住shell中的命令由空格分隔。 因此,在这种情况下,命令不是. ,但是./run.sh :这意味着将执行子shell并且exit将仅对子shell有效。

三种方式:

您可以将脚本包含在函数中,并仅使用return。

 #!/usr/bin/env bash main() { ... return 1 ... } main "$@" 

您可以测试脚本是否由交互式shell提供。

 if [[ $- = *i* ]]; then return 1 else exit 1 fi 

您可以尝试返回,如果失败,请退出。

 return 1 2>/dev/null || exit 1 

将命令’source’想象为’include’语句。 它接受参数的内容并将其运行,就像它直接运行一样。 在这种情况下,您的命令是’source’,参数为’run.sh’,run.sh的执行方式就像您在命令行中键入run.sh的内容一样。

当您运行’./run.sh’时,’。/ run.sh’是您的命令,它没有参数。 由于此文件是纯文本而不是二进制文件,因此shell会在shebang(第一行的“#!”)中查找解释器并找到“/ bin / bash”。 所以你的shell然后启动一个新的bash实例,run.sh的内容在这个新实例中运行。

在第一个实例中,当bash到达’exit’命令时,它的执行方式就像您在命令行中键入它一样。 在第二个实例中,它在shell启动时在bash进程中执行,因此只有这个bash实例才会收到’exit’命令。

当您在bash中键入一行时,第一个空格之前的任何内容都被视为命令,后面的任何内容都被视为参数。 命令 ‘。’ 是’source’的别名。 当你跑’。 run.sh’the’。’ 是一个自己的命令,因为它通过空格与它的参数分开。 当你运行’./run.sh’时,你的命令是’./run.sh’和’。’ 是带有’。’的run.sh的相对路径的一部分。 代表您当前的文件夹。