如何在变量中获取 bash 命令的输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12738460/
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
How to get output of a bash command in a variable
提问by Chris O'Kelly
I have been following through some of the similar questions (such as How to set a variable to the output from a command in Bash?), however the accepted answers seem to be non-working for me. I wasn't sure whether I ought to derail someone else's question or post my own duplicate, so apologies if I chose wrong here.
我一直在关注一些类似的问题(例如How to set a variable to the output from a command in Bash?),但是接受的答案似乎对我不起作用。我不确定我是否应该破坏别人的问题或发布我自己的副本,所以如果我在这里选择错误,请道歉。
I wish to get the output and exit status of a number of commands in a script I am putting together. Here is an example of what I have been using:
我希望在我放在一起的脚本中获得许多命令的输出和退出状态。这是我一直在使用的示例:
cmd_output=$(rm $file)
exit_status=$?
if [ "${exit_status}" -eq 0 ]
then
log "Successfully removed the original" ${TAB_LEVEL}
else
fail "Failed to remove the original, the output was: \n ${cmd_output}"
fi
The log and fail functions are:
log 和 fail 函数是:
# Usage: fail "Failure message"
function fail {
echo "FATAL ERROR: " >> "${LOG_DIR}/${LOG_FILE}"
exit 1
}
# Usage: log "Log message" 3 Where the tab-level is 3.
function log {
if (("" > 0))
then
eval "printf ' %.0s' {1..}" >> "${LOG_DIR}/${LOG_FILE}"
fi
echo "" >> "${LOG_DIR}/${LOG_FILE}"
return 0
}
In the example above I use the $(cmd) format, but I have also tried using backticks.
在上面的例子中,我使用了 $(cmd) 格式,但我也尝试过使用反引号。
In my log file, all I see when there is a failure is:
在我的日志文件中,出现故障时我看到的只是:
FATAL ERROR: Failed to remove the original, the output was: \n
致命错误:无法删除原始文件,输出为:\n
Also, the output of the failed commands ends up on screen as per usual. Is there a common reason that my cmd_output variables would be remaining empty?
此外,失败命令的输出照常在屏幕上结束。我的 cmd_output 变量保持为空是否有一个常见的原因?
回答by Janito Vaqueiro Ferreira Filho
You have to include the output of the special standard error output stream:
您必须包含特殊标准错误输出流的输出:
cmd_output=$(rm "$file" 2>&1)
There are three default streams on every program (that are numbered file descriptors):
每个程序都有三个默认流(它们是编号的文件描述符):
0. Standard input (where the program normally reads from)
1. Standard output (where the program normally writes to)
2. Standard error (where the program normally writes error messages)
So to capture the error messages, we must redirect standard error output (stderr) into normal standard output (stdout) which will then be captured by the $(...)
expression.
因此,要捕获错误消息,我们必须将标准错误输出 (stderr) 重定向到正常的标准输出 (stdout),然后该输出将被$(...)
表达式捕获。
The syntax for redirection is through the >
"operator". Immediately before it you tell which file descriptor to redirect (the default is 1, which is stdout). And you can specify it to redirect to a file. If you write an ampersand (&
) after it, you force it to redirect into another file descriptor. Therefore, in this example, we redirect file descriptor 2 (stderr) into file descriptor 1 (stdout).
重定向的语法是通过>
“operator”。紧接在它之前,您告诉要重定向哪个文件描述符(默认值为 1,即标准输出)。你可以指定它重定向到一个文件。如果&
在它后面写一个 & 符号 ( ),则会强制它重定向到另一个文件描述符。因此,在本例中,我们将文件描述符 2 (stderr) 重定向到文件描述符 1 (stdout)。
Also, you can also redirect input with <
"operator", but in this case the default file descriptor is 0 (stdin).
此外,您还可以使用<
“operator”重定向输入,但在这种情况下,默认文件描述符为 0 (stdin)。
Another observation is that it is probably good practice to place your $file
variable between double quotes, in case it has white space characters.
另一个观察结果是,将$file
变量放在双引号之间可能是一种很好的做法,以防它有空格字符。
Hope this helps a little =)
希望这会有所帮助 =)
回答by antak
*nix command generally have two forms of output:standard output (stdout
) and standard error (stderr
).
* nix 命令一般有两种输出形式:标准输出 ( stdout
) 和标准错误 ( stderr
)。
FOO=$(...)
only captures stdout
, and leaves stderr
unhindered.
FOO=$(...)
只捕获stdout
,stderr
并不受阻碍地离开。
If you want the contents of stderr
with this syntax, you need to postfix your command with 2>&1
so that stderr
is merged into stdout
. (e.g. like so: rm $file 2>&1
)
如果您想要stderr
使用此语法的内容,则需要后缀您的命令,2>&1
以便将stderr
其合并到stdout
. (例如像这样:rm $file 2>&1
)
回答by William Pursell
Since your fail
function is just exiting, it would be a lot easier to simply do:
由于您的fail
函数刚刚退出,因此简单地执行以下操作会容易得多:
set -e # Abort on failure
exec 2>> "${LOG_DIR}/${LOG_FILE}" # Append all errors to LOG_FILE
if cmd_output=$(rm $file)
log "Successfully removed the original" ${TAB_LEVEL}
fi
The only difference between this and the original code is that it does not
print the text FATAL ERROR:
. Since brevity is a virtue, it would probably
be better to skip the log
function entirely. Report errors loudly; succeed
silently.
这与原始代码之间的唯一区别是它不打印文本FATAL ERROR:
。由于简洁是一种美德,因此log
完全跳过该功能可能会更好。大声报告错误;默默地成功。