如何在单个语句中检查命令退出状态是否为零且 stderr 是否为空?
How to check that both command exit status is zero and stderr is empty in a single statement?
有些命令向 stderr
写入无关紧要的警告,但 return 退出状态 0
。
有没有办法检查命令退出状态是 0
和 stderr
是空的,没有创建临时文件和一个单一的语句?
我建议:
stderr=$(your_command 2>&1 >/dev/null)
[[ $? == 0 ]] && [[ ${#stderr} == 0 ]] && echo okay
希望以下内容对您有所帮助。
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;
}
由于 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"
}
感谢 and 的评论:
if stderr=$(command 2>&1 >/dev/null) && test -z "$stderr"; then echo "ok"; fi
command 2>&1 >/dev/null
的 stderr
被重定向到 stdout
之前的位置,stdout
本身被重定向到 /dev/null
。
然后将stderr
赋值给stderr=$(command 2>&1 >/dev/null)
中的stderr
变量,这次赋值的退出码就是command
中的那个,所以在[=20中使用了=].然后,如果 command
的退出代码为零(并且仅在这种情况下),则检查第二个条件 (test -z "$stderr"
) - 测试 $stderr
变量是否为零长度字符串.
有些命令向 stderr
写入无关紧要的警告,但 return 退出状态 0
。
有没有办法检查命令退出状态是 0
和 stderr
是空的,没有创建临时文件和一个单一的语句?
我建议:
stderr=$(your_command 2>&1 >/dev/null)
[[ $? == 0 ]] && [[ ${#stderr} == 0 ]] && echo okay
希望以下内容对您有所帮助。
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;
}
由于 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"
}
感谢
if stderr=$(command 2>&1 >/dev/null) && test -z "$stderr"; then echo "ok"; fi
command 2>&1 >/dev/null
的 stderr
被重定向到 stdout
之前的位置,stdout
本身被重定向到 /dev/null
。
然后将stderr
赋值给stderr=$(command 2>&1 >/dev/null)
中的stderr
变量,这次赋值的退出码就是command
中的那个,所以在[=20中使用了=].然后,如果 command
的退出代码为零(并且仅在这种情况下),则检查第二个条件 (test -z "$stderr"
) - 测试 $stderr
变量是否为零长度字符串.