Skip to content

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.shsource foo.sh 的另外一种写法。这种方式去运行脚本跟使用 bash foo.sh 的方式有不同的地方。

当我们使用 source 来执行脚本的时候,它并不会使用一个新的子进程来执行,而是直接在当前进程中执行。这就意味着脚本中定义的变量跟执行的操作都会影响当前进程。还是以前面的 foo.sh 来举例。当执行 source foo.sh 之后,我们在父进程中再次执行 echo ${cat_name} 会发现输出的内容不再为空,而是 Hello Kitty

这也是为什么我们在 ~/.bashrc 中修改环境变量的之后,在不重启终端的情况下,通过执行 source .bashrc 能让设置生效的原因。