我正在編寫一個腳本,用於檢測我的 Linux 電腦上是否已運行該實例,並在螢幕上顯示實例的數量。
“Detect_itself.sh”腳本的內容是:
#!/bin/sh
INSTANCES_NUMBER=`ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
echo "Number of detect_itself.sh instances running now =" $INSTANCES_NUMBER
echo "Second method:"
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
echo "Third method:"
echo `ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
echo "Please, press a key"
read -r key
執行腳本時,螢幕上顯示:
Number of detect_itself.sh instances running now = 2
Second method:
1
Third method:
2
Please, press a key
但我希望它能顯示:
Number of detect_itself.sh instances running now = 1
Second method:
1
Third method:
1
Please, press a key
我不明白為什麼如果我執行ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
它會返回值 1,但如果我將此值保存在變數中並用 echo 顯示它,它會顯示 2。
答案1
發生這種情況是因為您正在ps
子 shell 中執行該命令。當你運行這個時:
INSTANCES_NUMBER=`ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
這實際上分叉了一個新的子 shell 來運行該命令detect_itself.sh
。為了說明這一點,請執行以下命令:
#!/bin/sh
echo "Running the ps command directly:"
ps -ef | grep detect_itself.sh | grep -v -i grep
echo "Running the ps command in a subshell:"
echo "`ps -ef | grep detect_itself.sh | grep -v -i grep`"
應該列印:
$ test.sh
Running the ps command directly:
terdon 25683 24478 0 14:58 pts/11 00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
Running the ps command in a subshell:
terdon 25683 24478 0 14:58 pts/11 00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
terdon 25688 25683 0 14:58 pts/11 00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
幸運的是,有一個應用程式可以做到這一點!這種事情正是pgrep
存在的原因。因此,將您的腳本更改為:
#!/bin/sh
instances=`pgrep -fc detect_itself.sh`
echo "Number of detect_itself.sh instances running now = $instances"
echo "Second method:"
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
echo "Third method (wrong):"
echo `ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
應該列印:
$ detect_itself.sh
Number of detect_itself.sh instances running now = 1
Second method:
1
Third method (wrong):
2
重要的: 這不是一件安全的事。例如,如果您有一個名為 的腳本this_will_detect_itself
,則會將其計算在內。如果您在文字編輯器中開啟了該文件,那麼該文件也將被計算在內。對於此類事情,一種更可靠的方法是使用鎖定檔案。就像是:
#!/bin/sh
if [[ -e /tmp/I_am_running ]]; then
echo "Already running! Will exit."
exit
else
touch /tmp/I_am_running
fi
## do whatever you want to do here
## remove the lock file at the end
rm /tmp/I_am_running
或者,更好的是,考慮使用來trap
確保即使腳本崩潰時也會刪除檔案。詳細資訊將取決於您到底想要做什麼,以及為什麼需要檢測正在運行的實例。