以下命令将解析google ip
> ip=`dig +short google.com`
> echo $ip
> 216.58.210.238
有时(特别是当互联网连接丢失时)此命令失败并显示此错误
> ;; connection timed out; no servers could be reached
当命令失败并且我使用$#
时,输出为0用于赋值
> ip=`dig +short google.com`
> echo $#
> 0
> echo $ip # Command failed
> ;; connection timed out; no servers could be reached
如何在变量中保存命令输出,同时检查命令是否成功
你应该使用$?
而不是$#
。
$? - contains the return value from the last script.
$# - contains the total number of arguments passed to a script or function
做类似下面的事情:
if $?
then
echo "Success" # Do something here
else
echo "Fail" # Fallback mode
fi
编辑:回复this评论回答标题中的问题:
在变量上保存命令输出并检查退出状态
正如@chepner在this评论中指出的那样,任务不会干涉命令的退出状态。所以:
ip=$(dig +short google.com) # Just changed the legacy backticks to $()
[ $? -eq 0 ] && echo "dig succeeded"
您可以避免访问$?
,只需:
if ip=$(dig +short google.com); then
# Success.
else
# Failure.
fi
以下功能将打印“失败”并返回1。
print_and_fail() { printf '%s' fail; return 1; }
因此,如果我们执行以下操作:
if foo=$(print_and_fail); then printf '%s\n' "$foo";fi
我们没有输出,但是将print_and_fail
输出存储到$foo
- 在这种情况下,“失败”。
但是,看看下面的函数,它将打印“success”并返回0。
print_and_succeed() { printf '%s' success; return 0; }
让我们看看现在发生了什么:
$ if foo=$(print_and_succeed); then printf '%s\n' "$foo";fi
$ success
您可以检查返回或使用命令替换并检查结果变量。例如
$ ip=$(dig +short google.com)
$ [ -n "$ip" ] && echo "all good, ip = $ip"
(你可以用-z
反向检查失败
由于你使用的是Bash,你可以使用类似下面的脚本来捕获stdout,stderr和返回代码https://gist.github.com/jmmitchell/c4369acb8e9ea1f984541f8819c4c87b
为了便于参考,我在这里复制了脚本:
# #!/bin/bash
#
# based on posts from stackexchange:
# http://stackoverflow.com/a/26827443/171475
# http://stackoverflow.com/a/18086548/171475
# http://stackoverflow.com/a/28796214/171475
function example_function {
printf 'example output to stdout %d\n' {1..10}
echo >&2 'example output to stderr'
return 42
}
##############################
### using the dot operator ###
if [ "${BASH_VERSINFO}" -lt 4 ]; then
printf '%s\n' "The source version of this script requires Bash v4 or higher."
else
# stdout & stderr only
source <({ cmd_err=$({ mapfile -t cmd_out < <(example_function); } 2>&1; declare -p cmd_out >&2); declare -p cmd_err; } 2>&1)
printf "\n%s\n" "SOURCE VERSION : STDOUT & STDERR ONLY"
printf "%s\n" "${cmd_out[@]}"
printf "%s\n" "${cmd_err}"
unset cmd_out
unset cmd_err
# stdout & stderr only as well as return code:
source <({ cmd_err=$({ mapfile -t cmd_out< <( \
example_function \
; cmd_rtn=$?; declare -p cmd_rtn >&3); } 3>&2 2>&1; declare -p cmd_out >&2); declare -p cmd_err; } 2>&1)
printf "\n%s\n" "SOURCE VERSION : STDOUT, STDERR & RETURN CODE"
printf '%s\n' "${cmd_out[@]}"
# alternative version
# declare -p cmd_out
printf '%s\n' "${cmd_err}"
printf '%s\n' "${cmd_rtn}"
unset cmd_out
unset cmd_err
unset cmd_rtn
fi
##############################
######### using exec #########
# stdout & stderr only
eval "$({ cmd_err=$({ cmd_out=$( \
example_function \
); } 2>&1; declare -p cmd_out >&2); declare -p cmd_err; } 2>&1)"
printf "\n%s\n" "EVAL VERSION : STDOUT & STDERR ONLY"
printf '%s\n' "${cmd_out}"
printf '%s\n' "${cmd_err}"
printf '%s\n' "${cmd_rtn}"
unset cmd_out
unset cmd_err
# stdout & stderr only as well as return code:
eval "$({ cmd_err=$({ cmd_out=$( \
example_function \
); cmd_rtn=$?; } 2>&1; declare -p cmd_out cmd_rtn >&2); declare -p cmd_err; } 2>&1)"
printf "\n%s\n" "EVAL VERSION : STDOUT, STDERR & RETURN CODE"
printf '%s\n' "${cmd_out}"
printf '%s\n' "${cmd_err}"
printf '%s\n' "${cmd_rtn}"
unset cmd_out
unset cmd_err
unset cmd_rtn