有些命令会把无关紧要的警告写到 stderr
但返回退出状态 0
.
有没有办法检查命令的退出状态是否为------。0
和 stderr
是否为空,而不需要创建临时文件,只需要一条语句?
我建议。
stderr=$(your_command 2>&1 >/dev/null)
[[ $? == 0 ]] && [[ ${#stderr} == 0 ]] && echo okay
因为... set -o pipefail
工作,你可以在管道中抓取stderr,如果stderr上有什么东西,你可以从管道中以非零的退出状态退出。所以基本上 pipefail
做二进制和-ing或退出状态--如果命令退出时退出状态为非零。pipefail
以此状态使管道失败,如果命令以零退出状态退出,那么管道右侧将以非零退出状态失败,所以整个管道将以非零退出状态退出。
# Usage: exit_if_nonzero_or_stderr command [args...]
# Executes the command [args...] and
# exits with nonzero exit status
# if the command exits with nonzero exit status
# __or__
# the command outputs anything on stderr.
exit_if_nonzero_or_stderr() {
(
set -o pipefail
{ "$@" 1>&3 ;} 2>&1 | {
if IFS= read -r line; then
printf "%s\n" "$line"
cat
exit 1
fi
} >&2
) 3>&1
}
针对所有组合进行测试。
tester() {
for i in \
'echo 1; true;' \
'echo 1; false;' \
'echo 1; echo 2 >&2; true;' \
'echo 1; echo 2 >&2; false;'
do
eval "f() { $i }"
set -o pipefail
exit_if_nonzero_or_stderr f 2> >( \
sed 's/^/stderr: /' >&2) |
sed 's/^/stdout: /';
echo "f() { $i } -> exit status: $?";
done
}
tester
该 tester
输出。
stdout: 1
f() { echo 1; true; } -> exit status: 0
stdout: 1
f() { echo 1; false; } -> exit status: 1
stderr: 2
stdout: 1
f() { echo 1; echo 2 >&2; true; } -> exit status: 1
stdout: 1
stderr: 2
f() { echo 1; echo 2 >&2; false; } -> exit status: 1
另一种实现方式,更啰嗦,更耗费内存,但更多的posix-ish你可以抓取 stderr
到一个变量,并检查它是否为非零。
exit_if_nonzero_or_stderr2() {
local stderr ret
# redirect stdout to output with temporary file descriptor
# and grab stderr
{ stderr=$({ "$@" 1>&3 ;} 2>&1 ) ;} 3>&1
# remember return value
ret=$?
# if theres anything on stderr, output it
if [[ -n "$stderr" ]]; then
cat <<<"$stderr" >&2
# if stderr, always nonzero
return 1
fi
# else we return with the exit status of the command
return "$ret"
}
希望下面的内容对你有帮助。
res=$(./test.out 2 >&1)
if [ $? -eq 0 ];then
stdout=$res
echo $stdout
else
return_code=$?
std_err=$res
echo $stderr
fi
对应的C语言的test.c文件
#include <stdio.h>
int main ( ) {
printf( "hello " );
fprintf( stderr, "HELP!" );
printf( " world\n" );
return 1;
}
if stderr=$(command 2>&1 >/dev/null) && test -z "$stderr"; then echo "ok"; fi
The stderr
的 command 2>&1 >/dev/null
被重定向到 stdout
以前是,而且 stdout
本身被重定向到 /dev/null
.然后是 stderr
被分配给 stderr
中的变量 stderr=$(command 2>&1 >/dev/null)
,而这个任务的退出代码就是刚才的那个 command
因此,它被用于 if
那么,如果退出代码为 command
为零(仅在这种情况下),第二个条件(test -z "$stderr"
)被选中--这是在测试是否有 $stderr
变量是一个零长度的字符串。