SAKA'S BLOG

执行shell脚本

执行shell脚本

source命令

source <filename> 或者. <filename>用于执行指定的shell文件,文件路径可以是绝对路径也可以是相对路径。

编写一个例子测试以下,新建source.sh文件,内容如下:

1
2
3
4
5
#/bin/bash
hello(){
HELLO="hello world"
echo $HELLO
}

在这个文件中定义了一个函数hello,定义了一个变量HELLO,然后输出hello world

此时执行shell命令`hello`,输出如下:

1
2
3
4
5
saka@saka-Vostro-3660:~/文档/Markdown/shell命令$ hello
程序 'hello' 已包含在下列软件包中:
* hello
* hello-traditional
请尝试:sudo apt install <选定的软件包>

此时并没有我们定义的函数,所以不能执行.
我们执行source命令后再看

1
2
3
4
5
saka@saka-Vostro-3660:~/文档/Markdown/shell命令$ source source.sh 
saka@saka-Vostro-3660:~/文档/Markdown/shell命令$ hello
hello world
saka@saka-Vostro-3660:~/文档/Markdown/shell命令$ echo $HELLO
hello world

可以看到已经可以执行hell函数了,并且能输出变量HELLO(shell中的变量全部为全局变量,用local声明的为局部变量).

sh/bash命令

bash <fileanme>或者sh <filename>也可以用来执行shell脚本.

1
2
3
 ~/Downloads/Markdown/shell命令/ bash source.sh
 ~/Downloads/Markdown/shell命令/ hello
zsh: command not found: hello

并没有得到我们的预期结果,发生什么了?我们知道子shell中的变量在父shell中是获取不到的,所以猜测此处是在子进程中执行的脚本。验证一下。我们修改一下source.sh文件,开始添加:

1
echo "file process id $$"

然后执行如下:

1
2
3
4
5
6
7
8
bash-3.2$ echo $$ #打印当前进程的id
25390
bash-3.2$ source source.sh
file process id 25390
bash-3.2$ . source.sh
file process id 25390
bash-3.2$ bash source.sh
file process id 25412

可以看到,source和.命令是在当前环境中执行的,而bash命令是在子shell中的进程中执行的,所以不会输出hello函数。

./\命令

这个命令与bash直接执行类似,但是要执行必须添加权限x。来看一下结果

1
2
3
4
5
bash-3.2$ chmod +x source.sh    #添加执行权限
bash-3.2$ ./source.sh
file process id 25442
bash-3.2$ . source.sh
file process id 25390

可以看到也是在子shell的进程中执行的脚本。

综上得出结论:

  1. source与. 命令可以在当前bash环境中执行脚本,脚本中的函数和变量均加载到当前bash环境;
  2. bash/sh命令是在子进程的shell中执行脚本,脚本中的函数和变量不会输出到当前bash环境中;
  3. 为脚本文件添加执行权限后运行也是在子进程中执行脚本。