我想写这样的代码:
command="some command"
safeRunCommand $command
safeRunCommand() {
cmnd=$1
$($cmnd)
if [ $? != 0 ]; then
printf "Error when executing command: '$command'"
exit $ERROR_CODE
fi
}
但是这段代码没有按我想要的方式工作。我哪里出错了?
下面是固定代码:
#!/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
是不必要的,但这是一个很好的做法。它使cmnd
和ret_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。
我用KornShell和Bash测试过。它运行得很好。
Try
safeRunCommand() {
"$@"
if [ $? != 0 ]; then
printf "Error when executing command: '$1'"
exit $ERROR_CODE
fi
}
应该是$cmd
而不是$($cmd)
。它在我的盒子上工作得很好。
您的脚本只适用于一个单词的命令,如ls。它将不工作的"ls "为此,将cmd="$1"; $cmd
替换为"$@"
。并且,不要以command="some cmd"; safeRun command
的身份运行脚本。作为safeRun some cmd
运行
另外,当您必须调试Bash脚本时,请使用'-x'标志执行。[bash -x .sh].
你的脚本有几个问题。
函数(子程序)应该在尝试调用它们之前声明。您可能希望从子例程返回()而不是退出(),以允许调用块测试特定命令的成功或失败。除此之外,您没有捕获'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
通常的想法是运行命令,然后使用$?
获取退出代码。但是,有时在多种情况下需要获得退出代码。例如,您可能需要隐藏它的输出,但仍然返回退出代码,或者打印退出代码和输出。
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