用於計算執行實例數量的 Bash 腳本不起作用

用於計算執行實例數量的 Bash 腳本不起作用

我正在編寫一個腳本,用於檢測我的 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確保即使腳本崩潰時也會刪除檔案。詳細資訊將取決於您到底想要做什麼,以及為什麼需要檢測正在運行的實例。

相關內容