在bash / ksh中获取命令的退出代码

时间:2011-11-21 12:32:18

标签: bash unix ksh exit

我想写这样的代码:

command="some command"

safeRunCommand $command

safeRunCommand() {
   cmnd=$1

   $($cmnd)

   if [ $? != 0 ]; then
      printf "Error when executing command: '$command'"
      exit $ERROR_CODE
   fi
}

但是这段代码没有按照我想要的方式运行。 哪里弄错了?

5 个答案:

答案 0 :(得分:65)

以下是固定代码:

#!/bin/ksh
safeRunCommand() {
  typeset cmnd="$*"
  typeset ret_code

  echo cmnd=$cmnd
  eval $cmnd
  ret_code=$?
  if [ $ret_code != 0 ]; then
    printf "Error : [%d] when executing command: '$cmnd'" $ret_code
    exit $ret_code
  fi
}

command="ls -l | grep p"
safeRunCommand "$command"

现在,如果你查看这段代码,我改变的一些事情就是:

  • 使用typeset不是必要的,而是一种很好的做法。它使cmndret_code属于safeRunCommand
  • 使用ret_code不是必需的,但是将返回代码存储在某个变量中(并尽快存储)是一种很好的做法,以便您可以像我在printf "Error : [%d] when executing command: '$command'" $ret_code
  • 中一样使用它
  • 使用围绕命令的引号传递命令,如safeRunCommand "$command"。如果您不这样做,cmnd将只获得值ls而不是ls -l。如果您的命令包含管道,则更为重要。
  • 如果您想保留空格,可以使用typeset cmnd="$*"代替typeset cmnd="$1"。您可以尝试使用两者,具体取决于命令参数的复杂程度。
  • eval用于评估,以便包含管道的命令可以正常工作

注意:请记住一些命令将1作为返回码,即使没有像grep这样的错误。如果grep发现某些内容,则会返回0,否则为1.

我用KSH / BASH测试过。它工作得很好。如果你遇到问题,请告诉我。

答案 1 :(得分:5)

尝试

safeRunCommand() {
   "$@"

   if [ $? != 0 ]; then
      printf "Error when executing command: '$1'"
      exit $ERROR_CODE
   fi
}

答案 2 :(得分:2)

应该是$cmd而不是$($cmd)。在我的盒子上工作正常。

编辑:您的脚本仅适用于单字命令,例如ls。它不适用于“ls cpp”。要实现此目的,请将cmd="$1"; $cmd替换为"$@"。并且,不要将您的脚本作为command="some cmd"; safeRun command运行,请将其作为safeRun some cmd运行。

此外,当您必须调试bash脚本时,请使用'-x'标志执行。 [bash -x s.sh]。

答案 3 :(得分:1)

你的剧本有几个问题。

在尝试调用函数(子例程)之前,应该声明它们。您可能希望从子例程返回()而不是exit(),以允许调用块测试特定命令的成功或失败。除此之外,您不会捕获'ERROR_CODE',因此始终为零(未定义)。

使用花括号包围变量引用也是一种很好的做法。您的代码可能如下所示:

#!/bin/sh
command="/bin/date -u"          #...Example Only

safeRunCommand() {
   cmnd="$@"                    #...insure whitespace passed and preserved
   $cmnd
   ERROR_CODE=$?                #...so we have it for the command we want
   if [ ${ERROR_CODE} != 0 ]; then
      printf "Error when executing command: '${command}'\n"
      exit ${ERROR_CODE}        #...consider 'return()' here
   fi
}

safeRunCommand $command
command="cp"
safeRunCommand $command

答案 4 :(得分:0)

通常的想法是运行命令然后使用$?来获取退出代码。但是,有时您有多种情况需要获取退出代码。例如,您可能需要隐藏它的输出但仍返回退出代码,或者同时打印退出代码和输出。

ec() { [[ "$1" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }

这将为您提供禁止输出您想要退出代码的命令的选项。当命令的输出被抑制时,函数将直接返回退出代码。

我个人喜欢将此功能放在我的.bashrc文件

下面我将演示一些可以使用它的方法:

# In this example, the output for the command will be
# normally displayed, and the exit code will be stored
# in the variable $ec.

$ ec echo test
test
$ echo $ec
0
# In this example, the exit code is output
# and the output of the command passed
# to the `ec` function is suppressed.

$ echo "Exit Code: $(ec -h echo test)"
Exit Code: 0
# In this example, the output of the command
# passed to the `ec` function is suppressed
# and the exit code is stored in `$ec`

$ ec -h echo test
$ echo $ec
0

使用此功能解决您的代码

#!/bin/bash
if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
    echo "Error when executing command: 'grep p' [$ec]"
    exit $ec;
fi
  

您还应该注意,您将看到的退出代码将用于正在运行的grep命令,因为它是正在执行的最后一个命令。不是ls