在 bash/ksh 中获取命令的退出代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8211844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get exit code for command in bash/ksh
提问by Kolesar
I want to write code like this:
我想写这样的代码:
command="some command"
safeRunCommand $command
safeRunCommand() {
cmnd=
$($cmnd)
if [ $? != 0 ]; then
printf "Error when executing command: '$command'"
exit $ERROR_CODE
fi
}
But this code does not working the way I want. Where I made mistake?
但是这段代码没有按照我想要的方式工作。我哪里出错了?
回答by havexz
Below is the fixed code:
下面是固定代码:
#!/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"
Now if you look into this code few things that I changed are:
现在,如果您查看此代码,我更改的几件事是:
- use of
typeset
is not necessary but a good practice. It makecmnd
andret_code
local tosafeRunCommand
- use of
ret_code
is not necessary but a good practice to store return code in some variable (and store it ASAP) so that you can use it later like I did inprintf "Error : [%d] when executing command: '$command'" $ret_code
- pass the command with quotes surrounding the command like
safeRunCommand "$command"
. If you dont thencmnd
will get only the valuels
and notls -l
. And it is even more important if your command contains pipes. - you can use
typeset cmnd="$*"
instead oftypeset cmnd="$1"
if you want to keep the spaces. You can try with both depending upon how complex is your command argument. - eval is used to evaluate so that command containing pipes can work fine
- 使用
typeset
不是必需的,而是一种很好的做法。它使cmnd
和ret_code
本地safeRunCommand
- 使用 of
ret_code
不是必需的,而是将返回代码存储在某个变量中(并尽快存储)的好做法,以便您可以像我在后面那样使用它printf "Error : [%d] when executing command: '$command'" $ret_code
- 传递带有引号的命令,例如
safeRunCommand "$command"
. 如果你不这样做,那么cmnd
只会得到价值ls
而不是ls -l
. 如果您的命令包含管道,则更为重要。 - 如果要保留空格
typeset cmnd="$*"
,typeset cmnd="$1"
则可以使用代替。您可以根据命令参数的复杂程度来尝试两者。 - eval 用于评估,以便包含管道的命令可以正常工作
NOTE: Do remember some commands give 1 as return code even though there is no error like grep
. If grep
found something it will return 0 else 1.
注意:请记住,即使没有像grep
. 如果grep
找到一些东西,它将返回 0 否则返回 1。
I had tested with KSH/BASH. And it worked fine. Let me know if u face issues running this.
我已经用 KSH/BASH 测试过。它工作得很好。如果您在运行此程序时遇到问题,请告诉我。
回答by sehe
Try
尝试
safeRunCommand() {
"$@"
if [ $? != 0 ]; then
printf "Error when executing command: ''"
exit $ERROR_CODE
fi
}
回答by Priyank Bhatnagar
It should be $cmd
instead of $($cmd)
. Works fine with that on my box.
它应该$cmd
代替$($cmd)
. 在我的盒子上很好用。
Edit:Your script works only for one-word commands, like ls. It will not work for "ls cpp". For this to work, replace cmd="$1"; $cmd
with "$@"
. And, do not run your script as command="some cmd"; safeRun command
, run it as safeRun some cmd
.
编辑:您的脚本仅适用于单字命令,例如 ls。它不适用于“ls cpp”。为此,请替换cmd="$1"; $cmd
为"$@"
. 并且,不要将脚本作为command="some cmd"; safeRun command
运行,而是作为safeRun some cmd
.
Also, when you have to debug your bash scripts, execute with '-x' flag. [bash -x s.sh].
此外,当您必须调试 bash 脚本时,请使用“-x”标志执行。[bash -x s.sh]。
回答by JRFerguson
There are several things wrong with your script.
您的脚本有几处错误。
Functions (subroutines) should be declared before attempting to call them. You probably want to return() but not exit() from your subroutine to allow the calling block to test the success or failure of a particular command. That aside, you don't capture 'ERROR_CODE' so that is always zero (undefined).
函数(子程序)应该在尝试调用它们之前声明。您可能希望从子例程中返回()而不是退出(),以允许调用块测试特定命令的成功或失败。除此之外,您不会捕获“ERROR_CODE”,因此它始终为零(未定义)。
It's good practice to surround your variable references with curly braces, too. Your code might look like:
用大括号将变量引用括起来也是一种很好的做法。您的代码可能如下所示:
#!/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
回答by Nathan F.
The normal idea would be to run the command and then use $?
to get the exit code. However, some times you have multiple cases in which you need to get the exit code. For example, you might need to hide it's output but still return the exit code, or print both the exit code and the output.
通常的想法是运行该命令,然后使用它$?
来获取退出代码。但是,有时您有多种情况需要获取退出代码。例如,您可能需要隐藏它的输出但仍返回退出代码,或者同时打印退出代码和输出。
ec() { [[ "" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }
This will give you the option to suppress the output of the command you want the exit code for. When the output is suppressed for the command, the exit code will directly be returned by the function.
这将使您可以选择抑制想要退出代码的命令的输出。当命令的输出被抑制时,退出代码将直接由函数返回。
I personally like to put this function in my .bashrc
file
我个人喜欢把这个函数放在我的.bashrc
文件中
Below I demonstrate a few ways in which you can use this:
下面我演示了几种可以使用它的方法:
# 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
Solution to your code using this function
使用此函数解决您的代码
#!/bin/bash
if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
echo "Error when executing command: 'grep p' [$ec]"
exit $ec;
fi
You should also note that the exit code you will be seeing will be for the
grep
command that's being run, as it is the last command being executed. Not thels
.
您还应该注意,您将看到的退出代码将用于
grep
正在运行的命令,因为它是正在执行的最后一个命令。不是ls
.