為什麼我得到不同的 ps 退出狀態 |grep 在腳本中?
我在腳本下面執行:
#!/bin/bash ps ax | grep -q [v]arnish if [ $? -eq 0 ];then echo varnish is running... exit 0 else echo "Critical : varnish is not running " exit 2 fi
輸出類似於::
[root@server ~]# sh -x check_varnish_pro.sh + ps ax + grep -q '[v]arnish' + '[' 0 -eq 0 ']' + echo varnish is running... varnish is running... + exit 0
當我在命令行中執行相同時,我的退出狀態為 1:
[root@server ~]# ps ax | grep -q [v]arnish; echo $? 1
這種情況就像清漆沒有安裝在伺服器中一樣。該腳本在安裝了 varnish 的伺服器上執行良好。
為什麼使用腳本和命令行執行時退出狀態不同?如何改進這個腳本?
當您執行名為
check_varnish_pro.sh
test的腳本時ps ax | grep -q [v]arnish
成功是因為有一個名為
check_
varnish_pro
的腳本正在執行。
一般來說,嘗試使用簡單方法
ps
並grep
嘗試確定給定程序是否正在執行是一個壞主意。你最好使用
pgrep
這個:if pgrep "varnish" >/dev/null; then echo "Varnish in running" else echo "Varnish is not running" fi
參見手冊
pgrep
。在某些系統上(可能不在 Linux 上),您會得到一個-q
標誌,該標誌對應於相同的標誌,grep
無需重定向到/dev/null
. 還有一個-f
標誌可以在完整的命令行上執行匹配,而不僅僅是在程序名稱上。也可以將匹配限制為屬於特定使用者的程序,使用-u
.安裝
pgrep
還允許您訪問pkill
允許您根據程序名稱發出信號的程序。此外,如果這是一個服務守護程序,並且如果您的 Unix 系統有一種方法可以查詢它的資訊(例如,它是否啟動和執行),那麼這是檢查它的正確方法。
在 Linux 上,你有
systemctl
(systemctl is-active --quiet varnish
如果它正在執行,將返回 0,否則返回 3),在 OpenBSD 上你有rcctl
,等等。現在到你的腳本:
在您的腳本中,您解析來自
ps ax
. 此輸出將包含腳本本身的名稱,check_varnish_pro.sh
顯然包含字元串varnish
。這會給你一個誤報。-q
如果您在測試時不帶標誌執行它,您就會發現這一點grep
。#!/bin/bash ps ax | grep '[v]arnish'
執行它:
$ ./check_varnish_pro.sh 31004 p1 SN+ 0:00.04 /bin/bash ./check_varnish_pro.sh
另一個問題是,儘管您嘗試通過在模式中使用來“隱藏”
grep
程序,使其不被grep
自身檢測到。[v]
如果您碰巧在其中包含文件或目錄的目錄中執行腳本或命令行,則該方法將失敗varnish
(在這種情況下,您將再次得到誤報)。這是因為該模式未加引號,shell 將使用它執行文件名通配。看:
bash-4.4$ set -x bash-4.4$ ps ax | grep [v]arnish + ps ax + grep '[v]arnish' bash-4.4$ touch varnish + touch varnish bash-4.4$ ps ax | grep [v]arnish + ps ax + grep varnish 91829 p2 SN+p 0:00.02 grep varnish
該文件的存在
varnish
將導致 shell 替換[v]arnish
為文件名,並且您在程序表(程序)varnish
中的模式上得到了命中。grep