今天檢查前同事留下的一個shell腳本時,其中一個腳本中有一個業務邏輯處理:要判斷Oracle資料庫實例是否啟動,如果資料庫實例處於OPEN狀態的話,則執行/運行一些業務邏輯操作。腳本大體如下(腳本做了一下混淆和精簡收縮) up_flag=`${SCRIPT_DIR}/chkdbup.sh ${OR ...
今天檢查前同事留下的一個shell腳本時,其中一個腳本中有一個業務邏輯處理:要判斷Oracle資料庫實例是否啟動,如果資料庫實例處於OPEN狀態的話,則執行/運行一些業務邏輯操作。腳本大體如下(腳本做了一下混淆和精簡收縮)
up_flag=`${SCRIPT_DIR}/chkdbup.sh ${ORACLE_SID}`
if [ ${up_flag} -eq 0 ]; then
.......
exit
else
.......
fi
其中chkdbup.sh腳本的內容如下:
ps -ef | grep -i smon_${1} | grep -v "grep" >/dev/null
echo $?
Review這個腳本時,我感覺這個腳本的邏輯有問題(我認為這個腳本存在一個邏輯"bug"),主要是{up_flag}不為0時則表示資料庫實例異常了
if [ ${up_flag} -eq 0 ]; then
.......
exit
else
.......
fi
在Linux shell腳本中,$?一般表示上一個命令的返回值(執行情況),執行成功,返回0,其他任何數值表示上條命令執行有錯誤。我認為資料庫實例OPEN或關閉或crash的時候,chkdbup.sh這個腳本都會返回0,而不會返回值1,為了驗證我的想法,於是我找了台測試環境驗證測試一下。當前測試環境下ORACLE_SID為kerry
[oracle@mytestdb ~]$ ps -ef | grep -i smon_kerry | grep -v "grep"
oracle 1338965 1 0 Jul05 ? 00:00:14 ora_smon_kerry
[oracle@mytestdb ~]$ echo $?
0
換一個ORACLE_SID,此時因為Oracle實例不存在,就可以模擬實例Crash的情況(懶得關閉Oracle實例了,這個跟關閉Oracle實例測試效果一致)
[oracle@mytestdb ~]$ ps -ef | grep -i smon_gsp | grep -v "grep"
[oracle@mytestdb ~]$ echo $?
1
按照我的想法/認知,不管這個資料庫實例存在或不存在,ps命令總是會執行成功,它就會返回0,而且是永遠返回0,但是測試驗證結果跟我的想法/認知不符合,Why?查了一些資料,然後和同事討論後,終於搞清楚了其中的原因,主要是因為$?命令獲取的上一條命令的返回結果,而上一條命令中使用了grep命令,而grep命令的返回結果是這樣的:如果找到了匹配的相關記錄則返回0,如果沒有找到匹配的相關記錄則返回1,如果執行過程中出錯,就返回2,你可以使用man grep查看相關說明,具體如下所示:
EXIT STATUS
Normally the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred. However,
if the -q or --quiet or --silent is used and a line is selected, the exit status is 0 even if an error occurred.
其實,grep命令在HP-UX下也是同樣的返回值,如下所示:
RETURN VALUE
Upon completion, grep returns one of the following values:
Hewlett-Packard Company - 3 - HP-UX 11i Version 3 Feb 2007
grep(1) grep(1)
0 One or more matches found.
1 No match found.
2 Syntax error or inaccessible file (even if matches were
found).
所以,我的想法/認知是錯誤的,而前同事也是在shell腳本中藉助grep這個特性和$?來判斷Oracle實例是否處於OPEN狀態。這個也是一個shell腳本中的一個技巧,只是我很少用這種技巧,另外,由於對grep命令返回的值不清楚(具體來說,不清楚grep沒有匹配到相關記錄時返回1)。因此鬧了一個烏龍事件。