当编译时失败时,编程语言Crystal当前不会写入STDERR。如果退出状态不为0并且仍然返回退出状态,我需要将STDOUT重定向到STDERR。
答案 0 :(得分:3)
从字面上看,您的请求几乎是不可能的:重定向在命令启动之前执行,而退出状态仅在退出时才知道。
但是,您可以无条件重定向到缓冲区,然后在退出状态已知后将该缓冲区写入stdout或stderr。
考虑一个类似于以下内容的包装器:
#!/bin/sh
if output=$("$@"); then
printf '%s\n' "$output"
else
retval=$?
printf '%s\n' "$output" >&2
exit "$retval"
fi
...调用为(如果保存为stderr-wrapper
):
stderr-wrapper your-program arg1 arg2 ...
答案 1 :(得分:1)
Roundabout管道方法,需要tac
和无害eval
,但既不是缓冲变量,也不是临时文件。
演示脚本demo
,使用echo false ; false
模拟输出到 stdout 的程序,并返回错误代码“ 1 ”。
#!/bin/bash
out=([0]=/dev/stdout [1]=/dev/stderr)
{ { echo $1 ; $1 ; echo $? ; } | tac ; } | \
{ read x ; eval tac \> ${out[$x]} ; exit $x ; }
证明,使用annotate-output
:
annotate-output +'' ./demo true ; echo --- ; annotate-output +'' ./demo false
I: Started ./demo true
O: true
I: Finished with exitcode 0
---
I: Started ./demo false
E: false
I: Finished with exitcode 1
将demo
概括为stderr-wrapper
:
bash
:
#!/bin/bash
# Usage: stderr-wrapper program [ args... ]
out=([0]=/dev/stdout [1]=/dev/stderr)
{ { $@ ; echo $? ; } | tac ; } | \
{ read x ; eval tac \> ${out[$((x>0))]} ; exit $x ; }
对于 POSIX shell,(这里是dash
):
#!/bin/dash
# Usage: stderr-wrapper program [ args... ]
{ { "$@" ; echo $? ; } | tac ; } | \
{ read x ; eval tac 1\>\&$(((x>0)+1)) ; exit $x ; }
bash
版本如何运作:
tac
反转整个流,因此错误代码是第一个。 (如果流很长,则很贵。)read
一行,错误代码,存储在$x
。eval
$out
数组成员,对应于输出应该到达的设备,然后使用tac
将输出重新反转到该设备。