我有一个编译后的程序main.bin
应该打印:
hello world
another line
该程序在打印第一行后立即生成分段错误。
如果我在 shell (zsh) 中运行它,我会得到以下结果:
Hello world
[1] 3503 segmentation fault (core dumped) ./main.bin
但是,当我尝试重定向并使用部分标准输出时,什么也没有。这是由于丢失了标准输出缓冲区。因此,使用该unbuffer
工具,我可以让它正常工作:
$ unbuffer ./main.bin > tee out.log
Hello world
$ cat out.log
Hello world
好的。现在我还想捕获 shell 给出的分段错误消息:
$ (sh -c ./main.bin) 2> err.log
Hello world
$ cat err.log
Segmentation fault (core dumped)
好的,我可以分别获取两者。但是当我尝试将它们捕获在一起时,除了调用 main.bin 两次之外,我找不到其他方法。仅在子 shell 中使用 unbuffer 不会产生分段错误。并且单独调用该程序不会打印输出。
我的目标是制作一个脚本,在 stdout 中打印程序的(可能是部分)输出,并在 stderr 中打印 shell 由于有错误的程序可能生成的任何分段错误、堆栈溢出等。
我当前的解决方案(不再是,我发布了答案)是一个包含以下内容的脚本:
subject="$1"
out=$(unbuffer "$subject")
err=$(sh -c "$subject" 2>&1 1>/dev/null)
echo ">o> $out"
>&2 echo ">e> $err"
除了在脚本中调用 main.bin 两次并回显每个 std{out,err} 之外,是否有更优雅的方法来实现此目的?我一直在这里阅读其他类似的条目[1] [2] [3],但它们很麻烦,或者不能直接映射到我的问题。
答案1
答案2
一个可能的答案是使用两个不同的脚本:
- subrun.sh:这里我将stderr提取到文件中
./main.bin 2>err.log;
- run.sh:这里我收集未缓冲的标准输出,并将每个输出打印到相应的位置。另外,返回main.bin给出的返回码
echo "">out.log>err.log
unbuffer ./subrun.sh > out.log
ret_code="$?"
cat out.log #cat to stdout
cat err.log >&2 # cat to stderr
return $ret_code # return program's return code