有条件地重定向bas​​h输出,只在错误

时间:2017-02-11 18:04:42

标签: bash pipe stdout travis-ci stderr

是否存在简单的单行方式,或简单的函数,例如bash命令:

  1. 默认情况下,在成功时将cout和cerr管道传输到文件
    • 换句话说,请勿在成功时打印到终端。
  2. 如果发生错误(即非零返回)
    • 捕获错误代码
    • 从(1)
    • 打印文件
    • 返回错误代码
  3. 奖励:如果我可以默认使用1或2个字符重新启用打印
  4. ,我会很高兴

    动机:travis-ci对总log cout / cerr大小有4MB的限制。这会在超出构建时终止构建,因此我只想打印实际错误,但是当检测到错误时,travis也会终止,就像set -e一样。

2 个答案:

答案 0 :(得分:1)

我认为你需要的是:

ls real_file.txt > /tmp/out.txt 2>&1 || echo $? && cat /tmp/out.txt
ls non_existent.txt > /tmp/out.txt 2>&1 || echo $? && cat /tmp/out.txt

补充:在OP的反馈之后:

ls real_file.txt > /tmp/out.txt 2>&1 || (echo $? && cat /tmp/out.txt)
ls non_existent.txt > /tmp/out.txt 2>&1 || (echo $? && cat /tmp/out.txt)

答案 1 :(得分:0)

正如http://mywiki.wooledge.org/BashFAQ/106中所述,您可以为所有命令应用全局重定向。

所以你可以像这样开始你的脚本:

exec 3>&1 >log 2>&1

使用此命令,将新的fd 3分配给屏幕,现有的fd1将被发送到日志文件,stderr也将被发送到日志文件。

试试(或检查我的测试here

exec 3>&1 >log 2>&1
ls nofile #This will raise an error on stderr
echo "hello" #This would normally be printed on stdout / fd1
echo "hello again" >&3 #This will go in fd3
#Output:
hello again

$ cat log
ls: cannot access nofile: No such file or directory                                                                                                                             
hello

ls将失败(除非你有一个名为“nofile”的文件:))但错误信息将被发送到log gile。

echo将成功打印“hello”,但这将转到fd1,这意味着再次记录日志文件。

最后一个回复被重定向到fd3 =您的真实屏幕,这是您将在现实中看到的唯一消息。

前进一步,您可以使用$捕获每个命令结果? (或者如果要使用管道,则使用bash PIPESTATUS数组。)

另一项测试:

exec 3>&1 >log 2>&1
ls nofile; ex=$?; 
[[ "$ex" -ne 0 ]] && (echo "Oops, something gone wrong.Exit status = $ex" && cat log) >&3 

#Output
Oops, something gone wrong.Exit status = 2
ls: cannot access nofile: No such file or directory

替代方式

if ! ls nofile;then echo "something is wrong" >&3;fi

如果ls失败,将在屏幕上打印“有问题” 如果ls没有失败,则将结果打印到日志中,屏幕上看不到任何内容。

作为一般的想法,使用这样的方法,您可以将stderr和stdout始终重定向到文件,并且您可以通过在每个命令中应用>&3来选择性地在屏幕上打印消息,您希望它的结果是打印在屏幕上。

我不知道是否可以根据每个命令的退出状态进行自动重定向。这就是stderr的用途。打印错误。

您似乎需要在执行后监视每个命令的退出状态。

另外,请注意某些命令可能会根据执行的操作(即命令差异)返回不同于零的退出状态