如果启用了errexit,如何运行可能失败的命令并获取其退出代码?

时间:2017-05-20 01:22:37

标签: bash

我的所有脚本都打开了errexit;也就是说,我运行set -o errexit。但是,有时我想运行grep之类的命令,但是即使命令失败也要继续执行我的脚本。

我该怎么做?也就是说,如何在不删除整个脚本的情况下将命令的退出代码转换为变量?

我可以关闭errexit,但我不愿意。

3 个答案:

答案 0 :(得分:5)

如果失败的命令是“未经测试”,则errexit只会导致脚本终止。在FreeBSD上按man sh

         Exit immediately if any untested command fails in non-interactive
         mode.  The exit status of a command is considered to be explic-
         itly tested if the command is part of the list used to control an
         if, elif, while, or until; if the command is the left hand oper-
         and of an ``&&'' or ``||'' operator; or if the command is a pipe-
         line preceded by the ! keyword.

所以..如果你想使用这样的结构:

grep -q something /path/to/somefile
retval=$?
if [ $retval -eq 0 ]; then
  do_something  # found
else
  do_something_else  # not found
fi

你应该使用这样的结构:

if grep -q something /path/to/somefile; then
  do_something  # found
else
  do_something_else  # not found
fi

if关键字的存在使得grep命令 已经过测试 ,因此不受errexit的影响。这种方式可以减少打字。

当然,如果您真的需要变量中的退出值,那么没有什么可以阻止您使用$?

if grep -q something /path/to/somefile; then
  do_something  # found
else
  unnecessary=$?
  do_something $unnecessary  # not found
fi

答案 1 :(得分:1)

以下是实现此目的的方法:您可以为某些代码行“关闭”for train in train_files: with open(train) as f: row = [] col = [] for index, line in enumerate(f): record = line.rstrip().split(' ') row = row+[index]*(len(record)-4) col = col+record[4:] row = np.array(row) col = np.array(col) data = np.array([1]*len(row)) mtx = sparse.coo_matrix((data, (row, col)), shape=(n_row, max_feature)) mmwrite(train+'trans',mtx) ,然后在您决定时再次启用它:

set -o errexit

另一种选择如下:

set +e  #disables set -o errexit
grep -i something file.txt
rc="$?" #capturing the return code for last command
set -e #reenables set -o errexit

这将允许您捕获变量grep -i something file.txt || rc="$?" 上的返回码,而不会中断您的脚本。您甚至可以扩展最后一个选项来捕获并处理同一行上的返回代码,而不会有触发退出的风险:

rc

最后一位grep -i something file.txt || rc="$?" && echo rc="$?" > somefile.txt && command || : 将保证上面的行总是返回一个返回码= 0(真)。

答案 2 :(得分:1)

我能想到的最紧凑,最不重复的形式:

<command> && rc=$? || rc=$?

没有变量名称重复的表单 - rc=$(<command> && echo $? || echo $?) - 具有表达式rvalue,但也会捕获<command> 1 的标准输出。因此,如果您“知道”<command>没有正常输出,那么它是唯一安全的。

使用a && b || c构造is safe here因为rc=$?$(echo $?)永远不会失败。

1 当然,您可以通过摆弄文件描述符来解决这个问题,但这会使构造变得冗长且不方便作为标准