2016-04-28 148 views
2

以下命令将解决谷歌的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 

如何将命令的输出保存在变量中,同时检查命令是否成功

+1

如何是''#给你'0' – anubhava

+1

你混淆了'$#' (位置参数的数目)用'$?'(最后一个命令的退出状态)。 – chepner

回答

1

您应该使用$?而不是$#

$? - 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评论回答这个问题的标题:可变

保存命令的输出,并检查退出状态

由于@chepnerthis评论中指出,作业不会干涉命令的退出状态。所以:

ip=$(dig +short google.com) # Just changed the legacy backticks to $() 
[ $? -eq 0 ] && echo "dig succeeded" 
+2

这很好;纯赋值不会影响'$?'的值; 'ip = $(echo hello; exit 19); echo $?'会输出19. – chepner

+0

@chepner:我刚刚注意到了。 – sjsam

+0

@chepner是的,你是对的,我是检查存在状态错误,echo $?成功地工作 – Nasr

1

可避免访问$?,并简单:

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 - 在这种情况下,“失败”。

但是,看看下面的函数,它将打印“成功”并返回0

print_and_succeed() { printf '%s' success; return 0; } 

让我们来看看现在发生了:

$ if foo=$(print_and_succeed); then printf '%s\n' "$foo";fi 
$ success 
1

您可以检查返回或使用命令替换并检查生成的变量。例如

$ ip=$(dig +short google.com) 
$ [ -n "$ip" ] && echo "all good, ip = $ip" 

(你可以做失败的反向复用-z

-1

既然你正在使用bash,你可以使用类似下面的脚本,它可以捕获标准输出,标准错误和返回代码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 
+0

如果有人打算投我的答案,我会很感激在我的文章中了解我是错的还是无益的。 –