我有一個利基要求,即在另一個實用程式的包裝腳本中運行存盤在另一個組態檔中的命令。我的包裝器腳本(如下)適用于該組態檔中不使用“runuser”并且還包含引數的每個命令。如果命令使用 runuser 而我的“-c”命令包含引數,則腳本失敗。
包裝器腳本
#!/bin/bash
nagios_cmd=$(grep $1 /etc/nagios/nrpe.cfg | awk -F "=" {'print $2'})
exec=$($nagios_cmd)
if [ $? -eq 0 ]
then
#exitok
echo $exec
exit 0
else
#exitcritical
echo $exec
exit 1001
fi
組態檔
command[check_crsdb_state]=sudo /usr/lib64/nagios/plugins/check_crsdb_state
command[check_crsasm_state]=sudo /usr/lib64/nagios/plugins/check_crsasm_state
command[check_ora1_tablespace_apex]=sudo /usr/sbin/runuser -l oracle -c '/check_oracle_tablespace APEX 32000'
command[check_ora1_tablespace_lob1]=sudo /usr/sbin/runuser -l oracle -c '/check_oracle_tablespace LOB1 32000'
腳本運行成功
[root@quo-mai-ora1 /]# ./rmmwrapper.sh check_crsasm_state
OK - All nodes report 'Started,STABLE'
[root@quo-mai-ora1 /]#
腳本運行失敗
[root@quo-mai-ora1 /]# ./rmmwrapper.sh check_ora1_tablespace_apex
APEX: -c: line 0: unexpected EOF while looking for matching `''
APEX: -c: line 1: syntax error: unexpected end of file
[root@quo-mai-ora1 /]#
腳本運行失敗(使用 bash -x)
[root@quo-mai-ora1 /]# bash -x ./rmmwrapper.sh check_ora1_tablespace_apex
grep check_ora1_tablespace_apex /etc/nagios/nrpe.cfg
awk -F = '{print $2}'
nagios_cmd='sudo /usr/sbin/runuser -l oracle -c '\''/check_oracle_tablespace APEX 32000'\'''
sudo /usr/sbin/runuser -l oracle -c ''\''/check_oracle_tablespace' APEX '32000'\'''
APEX: -c: line 0: unexpected EOF while looking for matching `''
APEX: -c: line 1: syntax error: unexpected end of file
exec=
'[' 1 -eq 0 ']'
echo
exit 1001
[root@quo-mai-ora1 /]#
問題
您可以在 bash -x 輸出中看到,出于某種原因,當執行 $nagios_cmd 時,它在空格之前放置了單引號,用于分隔提供給結果腳本 (/check_oracle_tablespace) 的多個引數。我嘗試了不同的執行 $nagios_cmd 的方法(使用反引號代替等。我嘗試通過將組態檔修改為如下所示來轉義空格字符:
command[check_ora1_tablespace_apex]=sudo /usr/sbin/runuser -l oracle -c '/check_oracle_tablespace\ APEX\ 32000'
我還嘗試在 runuser 上的 -c 之后用雙引號而不是單引號封裝命令,或者根本不使用引號。
我顯然遺漏了 bash 的一些根本錯誤。我怎樣才能讓腳本只執行 $nagios_cmd 的內容,因為它以純文本形式出現?
uj5u.com熱心網友回復:
eval
這看起來像是真正正確答案的罕見情況之一。嘗試這個:
exec=$(eval "$nagios_cmd")
解釋:bash 直到決議命令程序的相當晚才擴展變數,因此變數中的字串不會像它實際上是命令的一部分那樣被決議。在這種情況下,問題是它在引號和轉義符被決議后被擴展,所以多詞命令周圍的單引號來不及達到預期效果。請參閱BashFAQ #50:“我試圖將命令放入變數中,但復雜的情況總是失敗!”
本質上是eval
從頭開始重新運行整個命令決議程序。因此,該變數會擴展為您要運行的命令(包括引號等),并且會像正常情況一樣對其進行決議。
請注意,我確實在變數周圍加上了雙引號;這樣它就不會經歷對未參考的變數參考完成的部分決議程序,然后再經歷完整的決議程序。這種一次半的決議程序可能會產生罕見但非常奇怪的效果,因此最好避免。
另外:eval
有一個當之無愧的壞名聲(我用“巨大的臭蟲磁鐵”這個詞來形容它)。這是因為它從根本上來說是將資料(例如變數的內容)視為可執行代碼,因此您很容易發現您正在做一些事情,例如將檔案名的一部分作為命令執行。但在這種情況下,您的資料應該是一個命令,并且(希望)相信不會包含惡意、無效等內容。在這種情況下,您希望資料被視為可執行代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/536483.html
標籤:Linux狂欢壳