Bash

Pipefail 阻止命令替換評估 pgrep?

  • April 20, 2022

我的目標是pgrep lftp -c在腳本中執行一個命令shell來檢查是否lftp已經在執行。

但以下腳本永遠不會超出“測試”輸出。只有當我pipefail完全刪除該行時,腳本才會執行。為什麼?

#!/usr/bin/env bash

set -e pipefail 

echo test

EXISTING="$(pgrep lftp -c)"
echo $EXISTING

首先,關於 shell 腳本最佳實踐指南的說明:避免為您自己的變數名使用大寫字母,因為這可能會導致與全域環境變數的命名衝突。舉一個明顯的例子,如果你命名一個變數PATH,它將覆蓋全域PATH變數,這意味著將不再在預期的位置找到執行檔。

現在,在您向我們展示的腳本中,沒有問題。它完全按預期工作:您正在使用set -e這意味著“如果任何命令失敗則退出”,如果任何命令返回非 0 退出狀態。如果pgrep沒有找到任何東西,它會以非 0 狀態退出,所以你的腳本就在那裡結束。

如果您手動嘗試,您可以看到它的實際效果:

$ pgrep lftp -c
0
$ echo $?
1

為避免這種情況,您可以使用wc代替pgrep -c,因為wc如果行數為 0,則不會以非 0 狀態退出:

#!/usr/bin/env bash

set -e  

echo test

existing="$(pgrep lftp | wc -l)"
echo "Found $existing instances of lftp"

lftp當沒有程序正在執行時,這會產生以下輸出:

$ foo.sh
test
Found 0 instances of lftp

如果你想設置 bash 的pipefail選項,你需要set -o pipefail,而不是set -e. 所以也許你真正想要的是:

#!/usr/bin/env bash

set -o pipefail 

echo test

existing="$(pgrep -c lftp)"
echo "Found $existing instances of lftp"

引用自:https://unix.stackexchange.com/questions/699718