最近在一个项目的自动化编译中遇到一些窝火shell的问题,在这里分享跟大家。
很多时候执行一个脚步可以有很多种方式,如:
source test.sh . test.sh
./test.sh /xx/xxx/test.sh
bash test.sh sh test.sh
如果在要求不高的情况下,上面的方式都是可执行的,比如你的脚步如下:
source . bash sh 执行脚本的时候 脚步对 source . bash sh 是有依赖的
./test.sh /xx/xxx/test.sh 则要求文件要有执行权限。
但很多时候是要求我们区分这些细节的。
source 和 .是等价的,执行的时候类似 C语言中的include,是在当前进程环境中执行。
bash 和 sh (如果sh指向bash), 那也是等价的,脚步被bash 装载,由bash来执行,fork了新进程
./test.sh /xx/xxx/test.sh 也是创建新进程来执行的。
忠告1. 请尽量在脚步前面加上路径
用下面的方式执行
执行结果是一样的吗?
如果文件在当前目录,在终端手动输入上面两条命令结果是一样的,都能输出 hello
但是如果有下面脚本呢
用source的方式执行
我们可以看到,执行的结果是一样的
但是直接执行呢?
我们发现soruce test.sh 不能正常执行,为什么呢?不是一样吗? 当前目录也是有这个文件的啊
source 执行一个脚步本,脚步运行的时候环境和shell终端输入时的环境是一样的,
打印为
这个时候处于非POSIX模式,执行的时候可以从当前目录中搜索文件
但是./test0.sh的时候发现
这时处于POSIX模式,搜索的文件需要带文件路径, ./形式的相对路径还是绝对路径都能找到文件。
为了方便脚步的移植,建议使用绝对路径。
忠告2. 尽量不要用source执行一个脚步
我们先来看一个脚本
这里打印了参数个数和第一个参数,
但是我们用下面的脚本来加载执行,结果会一样吗?
运行结果如下:
我们发现结果并不一样:
运行,显示有有一个参数
运行,显示0个参数。
为什么呢?
test0.sh 运行环境是 test1.sh 的顶层环境,./test0.sh 11 运行,显示顶层环境有1个参数,$1 是11
source 方式运行同顶层环境,没有fork子进程,所以test1.sh获取了顶层的参数环境,也有1个参数
./test.sh方式运行的时候,新fork了一个进程,所以参数个数为0
这种差异比较微小,在很多情况下,不会影响正常运行,但是如果在子shell中对参数做了判断,则可能会导致运行环境紊乱。
最怕的是这种情况出现在一个大的项目中,这个时候就会很难找出这个bug。
所以能直接执行尽量直接执行,能用绝对路径的尽量用绝对路径。