![](/img/trans.png)
[英]C++ program fails to produce output when redirecting stdout to a file on Linux
[英]How to stop redirecting stdout when one program fails in the chain?
在正常情況下,這將輸出 file.out
$ program1 | program2 | program3 > file.out
但是,如果發生了什么program1
失敗? 發生的情況是鏈的其余部分仍然會觸發並創建文件
$ false | echo worked > file.out
$ cat file.out
worked
我不希望文件出現。
還有另一篇關於此的 SO 文章建議添加 OR 子句,如下所示:
$ false | echo worked > file.out || rm file.out
ls file.out
file.out
這不起作用。 第二個命令觸發並算作成功。
同一篇 SO 文章還建議使用雙與號,如下所示:
$ program1 && program2 && program2 > file.out
這完全行不通。 在我的例子中 program2 期待來自 stdout 的輸出,所以這個鏈最終掛了,因為鏈沒有停止。 你可以通過一個簡單的例子來了解它是如何工作的:
$ echo something > stuff.txt
$ cat stuff.txt && false > file.out
something
$ cat file.out
它不是重定向輸出。
但是,更糟糕的是,當事情愉快時,它也不起作用。
$ echo something > stuff.txt
$ cat stuff.txt && true > file.out
something
$ cat file.out
在這種情況下,file.out 被創建並且它是空白的。 哦哦。
我接受了下面的答案。 調用set -o pipefail
是我需要的提示。 在我的實際情況中,我使用的是 Makefile。 為了使它在 Makefile 中工作,我將它添加到文件的頂部
SHELL=/bin/bash
然后到我的目標:
target:
@set -o pipefail; program1 | program2 | program3 > $@
當 bash 執行program1 | program2 | program3 > file.out
program1 | program2 | program3 > file.out
program1 | program2 | program3 > file.out
,它在 program1 啟動之前創建file.out
。 如果你想確保它永遠不會被創建,你需要緩沖輸出(在內存中或在臨時文件中)。 我發現最干凈的語法是這樣的:
if v=$( set -o pipefail; program1 | program2 | program3 ); then
echo "$v" > file.out
fi
或(這有不同的語義,忽略返回值。根據您的用例,這可能是可以接受的):
v=$( program1 | program2 | program3 )
test -n "$v" && echo "$v" > file.out
如果你可以創建文件然后刪除它,你可以這樣做
set -o pipefail
program1 | progam2 | program3 > file.out || rm file.out
如果您不想使用 pipefail(例如,因為您希望腳本可移植),您可以執行以下操作:
{ { { program1 || echo . >&3; } | { program2 || echo . >&3;} |
{ program3 || echo . >&3; } } 3>&1 >&4 |
if grep -q .; then exit 1; else exit 0; fi ; } 4>&1;
false | echo worked > file.out || rm file.out
以上是最接近你想要的; 如果您打開pipefail
選項,它將起作用。 喜歡
$ set -o pipefail
$ false | echo foo > file || rm -f file
$ ls file
ls: cannot access 'file': No such file or directory
關於管道的退出狀態,以及pipefail
的影響,手冊說
管道的返回狀態是最后一個命令的退出狀態,除非啟用了 pipefail 選項。 如果啟用了 pipefail,管道的返回狀態是最后一個(最右邊)命令的值,以非零狀態退出,如果所有命令都成功退出,則為零。
將您的命令包裝在函數中,您可以添加任何您想要的錯誤處理:
f_program1()
{
program1 || pkill -f program2
}
f_program2()
{
program2 || pkill -f program3
}
f_program3()
{
program3
}
f_program1 | f_program2 | f_program3 > file.out
我不確定pkill
是你最好的錯誤處理策略,所以把它當作一個占位符,因為函數可以讓你的麻煩消失。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.