使用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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章