[英]How do I detect a failed subprocess in a bash read statement?
在bash中,我們可以使用read
和pipe到一個子進程從一系列命令設置一個環境變量。 但是我在一個邊緣情況下檢測我的處理中的錯誤時遇到了問題 - 在錯誤發生之前,子流程管道的一部分會產生一些輸出。
一個采用輸入文件的簡化示例,查找以“foo”開頭的行,並將var
設置為該行的第一個單詞:
set -e
set -o pipefail
set -o nounset
die() {
echo $1 > /dev/stderr
exit 1
}
read -r var rest < <( \
cat data.txt \
| grep foo \
|| die "PIPELINE" \
) || die "OUTER"
echo "var=$var"
像data.txt
一樣運行它
blah
zap foo awesome
bang foo
將輸出
var=zap
在不包含foo
輸出的data.txt
文件上運行它(到stderr)
DEAD: PIPELINE
DEAD: OUTER
這一切都符合預期。
我們可以在流程結束時引入另一個cat
無操作階段
...
read -r var rest < <( \
cat data.txt \
| grep foo \
| cat \
|| die "PIPELINE" \
) || die "OUTER"
...
一切都繼續有效。
但是如果附加階段是paste -s -d' '
並且輸入不包含“foo”,則輸出為
var=
DEAD: PIPELINE
這似乎表明管道錯誤,但讀取成功與空行。 (看起來像paste -s -d' '
輸出一行輸出,即使它的輸入是空的。)
有沒有一種簡單的方法來檢測管道的這種故障,並導致主腳本出錯?
我想我可以檢查變量是不是空的 - 但這是一個簡化版本 - 我實際上是使用sed
和paste
來連接多行來設置多個變量,比如
read -r v1 v2 v3 rest < <( \
cat data.txt \
| grep "^foo=" \
| sed -e 's/foo=//' \
| paste -s -d' ' \
|| die "PIPELINE"
) || die "OUTER"
您可以使用另一個grep來查看paste
的輸出是否包含以下內容:
read -r var rest < <( \
cat data.txt \
| grep foo \
| paste -s -d' ' \
| grep . \
|| die "PIPELINE" \
) || die "OUTER"
最后,我根據具體情況選擇了兩種不同的解決方案。
第一種是將結果傳遞給臨時文件。 這將在執行讀取之前處理整個文件,因此管道中的任何故障都將導致腳本失敗。
cat data.txt \
| grep "^foo=" \
| sed -e 's/foo=//' \
| paste -s -d' ' \
> $TMP/result.txt
|| die "PIPELINE"
read -r var rest < $TMP/result.txt || die "OUTER"
第二個是測試變量是否已設置。 雖然這意味着我想避免一堆重復,但它似乎是最防彈的解決方案。
read -r var rest < <( cat data.txt \
| grep "^foo=" \
| sed -e 's/foo=//' \
| paste -s -d' ' \
|| die "PIPELINE"
) || die "OUTER"
[ ! -z "$var" ] || die "VARIABLE NOT SET"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.