我必须处理有时输出虚拟错误的编译器。在这种情况下,我不希望我的构建过程停止。相反,我只是想忽略错误并重新运行编译器:
%o: %c
$(prefix) dumb_compiler -c $^ -o $@ $(suffix)
我的目标是将内容定义为$prefix
和$suffix
以忽略虚拟错误。而不是dumb_compiler
让我们只考虑这个虚拟程序:
#!/usr/bin/perl
my $i = int rand 10;
die "Error -42\n" if $i > 5;
die "Error -12\n" if $i % 2;
print "$i\n";
发生Error -42
时,我想放弃stdout
,stderr
并再次运行程序,就像什么也没发生一样。在任何其他情况下,我想要打印程序将打印的内容。
我想在bash中将以下内容写成oneliner,将其放入Makefile
食谱中:
while True:
(_exit, _stdout, _stderr) = exec(program)
if _exit == 0 and "Error -42" not in _stderr:
print(stdout=_stdout, stderr=_stderr)
exit(_exit)
我目前写的这个,但它不起作用,它看起来不像oneliner
#!/usr/bin/bash
exit_status=0
run=1
exec 3>&1
exec 4>&2
while [ $run -eq 1 ];
do
run=0
./program 2>&4 1>&3
$exit_status=$?
if [ $exit_status -ne 0 ]
then
&4 > grep -q "Error -42"
if [ $? -ne 0 ]:
then
run=1
fi
fi
done
3>&1
4>&2
3>&-
4>&-
exit $exit_status
我的问题是如何正确执行程序执行中的stdout,stderr和退出状态,并在完成后将其清除?
我仍然可以尝试让我的程序正常运行,但我认为我的方法是错误的,这就是为什么我更愿意问SO。
答案 0 :(得分:3)
只需使用文件。重定向到其他文件句柄不会缓冲任何内容(在内存或磁盘上);他们不是解决方案。
while true; do
./program > /tmp/output 2> /tmp/error && break
exit_status=$?
grep -q "Error -42" /tmp/error || break
done
cat /tmp/output
cat /tmp/error >&2
exit $exit_status
这样做的一个小缺点是标准输出和标准错误不会交错,但这不应该是一个很大的损失。当它们都写入相同的文件句柄时,它们只是“正确”交错;一旦你将它们分开(如果你想在标准错误中找到Error -42
} ),你就失去了保留原始程序的相对顺序的能力制作它们。