Shell 脚本执行方式
执行 Shell 一般有以下几种方式:
./foo.sh
bash foo.sh
或者sh foo.sh
,这两者是等价的,因为/bin/sh/
其实就是/bin/bash
的链接文件source foo.sh
或者. foo.sh
,这两者是等价的。
在子进程中执行脚本
bash foo.sh
跟 ./foo.sh
这两种方式通过子进程来运行脚本命令,但是两者存在区别。
使用 sh foo.sh
的方式来执行脚本,当前进程会创建一个新的 bash 子进程来执行脚本命令。另外它还可以在没有给文件可执行权限的情况下运行脚本。而使用 ./foo.sh
也是产生一个子进程来运行脚本命令,但他是通过 Sha-Bang 的方式来解析运行脚本命令,另外这种方式要求文件有可执行权限。
需要注意的是,无论是使用 bash foo.sh
还是使用 ./foo.sh
运行脚本,当子进程执行完命令之后,不论脚本中是定义了变量,还是更改了当前目录,作用范围就只在子进程中,并不会影响到父进程。举个例子,假设 foo.sh
文件的内容如下:
bash
#!/bin/bash
cat_name="Hello Kitty"
echo ${cat_name}
当 foo.sh
执行完毕之后,我们在父进程中再次执行 echo ${cat_name}
会发现输出的内容是空的。
在父进程中执行脚本
. foo.sh
是 source foo.sh
的另外一种写法。这种方式去运行脚本跟使用 bash foo.sh
的方式有不同的地方。
当我们使用 source
来执行脚本的时候,它并不会使用一个新的子进程来执行,而是直接在当前进程中执行。这就意味着脚本中定义的变量跟执行的操作都会影响当前进程。还是以前面的 foo.sh
来举例。当执行 source foo.sh
之后,我们在父进程中再次执行 echo ${cat_name}
会发现输出的内容不再为空,而是 Hello Kitty
。
这也是为什么我们在 ~/.bashrc
中修改环境变量的之后,在不重启终端的情况下,通过执行 source .bashrc
能让设置生效的原因。