使用$?在if语句中的条件表达式

时间:2016-08-05 16:00:01

标签: linux bash

采用以下bash脚本:

ls: cannot access /sdfg: No such file or directory
Command failed: 0

输出将是:

<VirtualHost *:80>
  ProxyPass         /  http://localhost:8080/
  ProxyPassReverse  /  http://localhost:8080/
  ProxyRequests     Off
  <Proxy http://localhost:8080/*>
    Order deny,allow
    Allow from all
  </Proxy>
</VirtualHost>  

失败的ls命令实际上返回2,if语句捕获了这个,并且echos命令失败,但为什么$?得到更新到零?看起来if / then行被视为新命令。

3 个答案:

答案 0 :(得分:2)

[实际上是一个二进制文件,而不只是一些标点符号:

$ ls -l /usr/bin/[
-rwxr-xr-x 1 root root 51920 Feb 18 07:37 /usr/bin/[
$ /usr/bin/[ --version
[ (GNU coreutils) 8.25
Copyright (C) 2016 Free Software Foundation, Inc.

并且在某些系统上可能是test的符号链接。

所以这里

if [ $? -gt 0 ]

$?是您ls来电的结果,但此处

    echo "Command failed: $?"

$?是在前一行执行[的结果。

如果您想多次从命令中测试$?,您必须将其填入temp var:

ls blahblah
temp=$?
if [ $temp ... ]
if [ $temp ... ]

答案 1 :(得分:2)

您应该很少需要明确地检查$?,因为这样做的目的是if(以及其他条件内置函数,如while)。写这个的正确方法是

if ls /sdfg; then
    echo "Command succeeded: $?"
else
    echo "Command failed: $?"
fi

注意失败案例现在是else分支。 (如果您不特别关心保留失败退出代码,可以使用if ! ls ...并将成功分支保留在else中,但您的问题似乎是专门关于保留它,!的否定不会。)

答案 2 :(得分:2)

如果您要重复使用,请在测试命令后立即收集返回值

  File "/home/username/.virtualenvs/venv/local/lib/python2.7/site-packages/requests/adapters.py", line 467, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: SOCKSHTTPSConnectionPool(host='api-server.com', port=443): Max retries exceeded with url: /auth (Caused by NewConnectionError('<requests.packages.urllib3.contrib.socks.SOCKSHTTPSConnection object at 0x95c7ccc>: Failed to establish a new connection: SOCKS5 proxy server sent invalid data',))

但是,最佳做法是直接对命令的退出状态进行操作,而无需完全引用#!/bin/bash # best-practice: collect *on the same line*, so any logging added in the future doesn't # ...change your exit status. ls /sdfg; retval=$? if [ $retval -gt 0 ]; then echo "Command failed: $retval" # else echo "Command succeeded: $retval" fi

$?