我的问题类似于获取通过管道传输到另一个进程的退出状态,但我想获取管道中第二个命令的退出状态之内管道。
这是一个例子 -
false | echo $?
回报0
而非预期1
PIPESTATUS
给出之前的错误代码
false | echo $PIPESTATUS
返回0
第一次,然后返回1
,给出操作本身之后的结果。我的目的是创建一个像这样的函数:
debug() {
# Eventually will be formatted as JSON
echo "$(cat) was the result and the error code was $?"
}
(
echo "Foo"
false # To simulate an error
) | debug # debug should return "Foo was the result and the error code was 1"
答案1
你不能这样做,因为管道的两半执行同时地,所以右侧无法知道左侧是否成功。要执行您想要的操作,您必须先运行左侧命令,然后等待它退出。然后您可以显示命令的输出和退出代码。
您可能会发现此代码片段更适合您的目的:
myfunc() {
echo foo
read
}
out="$(myfunc)"
rc=$?
printf '%s was the result and the error code was %d\n' "$out" $rc
$ yes | ./test.sh
foo was the result and the error code was 0
$ ./test.sh < /dev/null
foo was the result and the error code was 1
答案2
吉姆的回答绝对是正确的。然而,在我的特定用例中,我发现该trap
命令为我提供了管道的干净语法,同时仍然捕获错误。
我最终选择了这个:
set -E
trap 'catch $? $LINENO' ERR
catch() {
echo "{ \"type\": \"error\", \"error\": \"$1\", \"line\": \"$2\" }"
exit $1
}
debug() {
# Eventually will be formatted as JSON
echo "$(cat) was the result"
}
(
echo "Foo"
# Simulate an error
false
echo "This should not be run!"
) | debug
其输出:
Foo
{ "type": "error", "error": "1", "line": "18" } was the result
如您所见,echo "This should not be run!"
从未被执行!
最后,将 JSON 格式化为用 替换换行符后\n
,您将得到以下结果:
{ "content": "Foo\n{ "error": "1", "line": "18" }" }
它需要一些后处理,特别是修复嵌套引号和/或将stdin
输入与trap
输出分开。