使用sh运行bash脚本的奇怪问题

在同一个文件夹下有两个脚本。a.sh和b.sh,脚本内容例如以下:
a.sh:

echo "test for a"
source b.sh

b.sh:

echo "test for b"

使用bash a.sh 返回正确结果。
而使用sh a.sh返回结果例如以下:
test for a
a.sh: line 2: source: b.sh: file not found
明显脚本运行过程中。没有找到文件b.sh,将a.sh脚本内容改动为例如以下:

echo "test for a"
source ./b.sh

再次使用sh a.sh 又能够正常运行了,这是为什么呢?

问题就出在sh与bash运行脚本的差别。
  首先要明白重要的一点:/bin/sh 尽管是/bin/bash的软连接,但这个软连接非常特殊,它并不仅仅仅仅是一个链接,sh不等于bash。假设你在CentOS下使用man sh能够找到这句话:
Bash can be configured to be POSIX-conformant by default.
这说明sh 等于 bash -posix 也就是说使用sh来运行一个脚本,所以使用sh a.sh的效果等同于bash -posix a.sh,尽管大部分情况下等于使用bash来运行脚本,但启用了bash的posix模式,也能够理解为posix标准。

那么就要遵循这个标准下的要求。


如今来man bash在关于source命令的文档中找到这么一句话:
When bash is not in posix mode, the current directory is searched if no file is found in PATH.
假设bash不是运行在posix模式下,当文件名称最为source的參数系统假设在PATH中,也就是系统变量中找不到这个文件时会在当前文件夹下查找这个文件。
所以在不使用posix模式的情况下 a.sh脚本中的source b.sh不会出错,由于即使在PATH中找不到。也会在当前文件夹中进行查找。但假设使用了posix模式,能够在google中找到关于bash posix mode的内容。当中有一条:
The . and source builtins do not search the current directory for the filename argument if it is not found by searching PATH.
.也就是source这样的内建命令在使用文件名称作为參数时,假设在PATH中无法找到。将不会在当前文件夹自己主动进行查找。
这就是问题的关键。使用了sh 运行a.sh,脚本中source b.sh中的b.sh既不会在PATH中被找到也不会在当前文件夹下被找到,那么bash仅仅会返回
b.sh: file not found
但假设a.sh写成这样 source ./b.sh
这就不一样了,这等于给source提供了一个该文件的路径,尽管是相对路径,但bash是能够依据脚本本身运行的位置来找到b.sh的,所以就不会出错了。

总结:所以普通情况下。在Linux中运行一个bash的脚本。我们都会使用bash去运行。就是为了避免这样的奇怪问题的产生。

关于bash posix mode的相关信息你能够在这里找到:
http://structure.usc.edu/bash/bashref_6.html#SEC83

posted @ 2017-05-28 17:51  mfmdaoyou  阅读(402)  评论(0编辑  收藏  举报