执行这样的脚本有什么区别:
./test.sh
并执行这样的脚本:
. test.sh
?
我尝试了一个简单的两行脚本,看看是否可以找到差异:
#!/bin/bash
ls
但两者. test.sh
都./test.sh
返回了相同的信息。
答案1
./test.sh
test.sh
作为一个单独的程序运行。如果文件以 .bashrctest.sh
开头#!/bin/bash
,则它可能是一个 bash 脚本。但也可能完全是另外一回事。
. ./test.sh
test.sh
在正在运行的 bash 实例中执行文件的代码。它的工作方式就好像内容文件test.sh
已以文本方式而不是行包含在内. ./test.sh
。 (几乎:有一些细节不同,例如 的值$BASH_LINENO
以及内置函数的行为return
。)
source ./test.sh
与 bash 中的相同. ./test.sh
(在其他 shell 中,source
可能略有不同或完全不存在;.
包含在 POSIX 标准中)。
./test.sh
使用内置脚本运行单独的脚本和包含内置脚本之间最常见的区别.
是,如果test.sh
脚本设置了一些环境变量,则使用单独的进程时,仅设置子进程的环境,而使用脚本包含时,环境变量将被设置。鞋底外壳工艺已设定。如果您在调用脚本foo=bar
中test.sh
及其echo $foo
末尾添加一行,您将看到差异:
$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo
$ . ./test.sh
$ echo $foo
bar
答案2
第一种方式运行脚本,将其作为子进程运行。另一方面,源代码(第二种方式)运行脚本,就好像您将其所有命令输入到当前 shell 中一样 - 如果脚本设置了变量,它将保持设置状态,如果脚本退出,您的会话将退出。请参阅help .
参考资料 文档。
答案3
我注意到的另一件事是,如果您有这样的别名:
# add into .bashrc_aliases
alias ls='ls -lht'
这样./test.sh
你就会得到一个正常的ls
输出(以及与当前 shell 不同的 PID):
auraham@pandora:~/iso$ ./test.sh
dsl-4.4.10.iso test.sh
3136 # PID
使用. test.sh
或. ./test.sh
您将获得更详细的输出(以及与当前 shell 相同的 PID):
auraham@pandora:~/iso$ echo $$
2767 # shell PID
auraham@pandora:~/iso$ . test.sh
total 50M
drwxrwxr-x 2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x 1 auraham auraham 32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r-- 1 auraham auraham 50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID
答案4
通常,a./file
只是指向文件的一种方式,在本例中,相当于 PWD(当前工作目录)路径后跟所使用的文件名。
$ pwd
/home/isaac/me/bin/
$ realpath ./file
/home/isaac/me/bin/file
行开头的路径(第一个参数或参数 0)也可能会向 shell 发出信号,要求其尝试执行该文件。如果它是一个 shell 脚本,那么 shell 很可能会加载它并在新的执行环境中执行它。如果它是其他形式的有效可执行文件,shell 将尝试通过内核exec
命令执行它。
在命令行中添加一个初始点(仅当整个参数为零时才有效)将允许使用已存在的相同执行环境加载 shell 脚本(不是外部可执行文件)。
$ . ./file # that exact same file as above, now it is sourced
$ source ./file # an equivalent (but longer) command.
当然,如果路径中没有设置目录(不是以点开头),则会涉及一些搜索来查找要获取的特定文件。
在bash中:
如果文件名不包含斜杠,则使用 PATH 中的文件名来查找包含文件名的目录。
并且,如果在 POSIX 模式下,PWD 也用于搜索给filename
定值。