我一直在关注一些类似的问题(例如How to set a variable to the output from a command in Bash?),但是接受的答案似乎对我不起作用。我不确定我是否应该讨论别人的问题或发布我自己的副本,所以如果我在这里选错了,请道歉。
我希望在我放在一起的脚本中获取许多命令的输出和退出状态。这是我一直在使用的一个例子:
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
日志和失败函数是:
# Usage: fail "Failure message"
function fail {
echo "FATAL ERROR: $1" >> "${LOG_DIR}/${LOG_FILE}"
exit 1
}
# Usage: log "Log message" 3 Where the tab-level is 3.
function log {
if (("${2}" > 0))
then
eval "printf ' %.0s' {1..$2}" >> "${LOG_DIR}/${LOG_FILE}"
fi
echo "$1" >> "${LOG_DIR}/${LOG_FILE}"
return 0
}
在上面的示例中,我使用$(cmd)格式,但我也尝试使用反引号。
在我的日志文件中,我发现失败的全部内容是:
致命错误:无法移除原件,输出为:\ n
此外,失败命令的输出最终会在屏幕上显示。是否有一个共同的原因,我的cmd_output变量将保持为空?
答案 0 :(得分:29)
您必须包含特殊标准错误输出流的输出:
cmd_output=$(rm "$file" 2>&1)
每个程序都有三个默认流(编号为文件描述符):
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)
因此,为了捕获错误消息,我们必须将标准错误输出(stderr)重定向到正常的标准输出(stdout),然后由$(...)
表达式捕获。
重定向的语法是通过>
“运算符”。在它之前,你告诉哪个文件描述符要重定向(默认值是1,这是stdout)。您可以指定它重定向到文件。如果在其后面写了一个&符号(&
),则强制它重定向到另一个文件描述符。因此,在此示例中,我们将文件描述符2(stderr)重定向到文件描述符1(stdout)。
此外,您还可以使用<
“operator”重定向输入,但在这种情况下,默认文件描述符为0(stdin)。
另一个观察结果是,将$file
变量放在双引号之间是个好习惯,以防它有空格字符。
希望这有点帮助=)
答案 1 :(得分:5)
* nix命令通常有两种输出形式:标准输出(stdout
)和标准错误(stderr
)。
FOO=$(...)
仅捕获stdout
,并stderr
不受阻碍。
如果您希望stderr
的内容具有此语法,则需要使用2>&1
对命令进行后缀,以便将stderr
合并到stdout
中。 (例如:rm $file 2>&1
)
答案 2 :(得分:0)
由于您的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
这与原始代码的唯一区别在于它没有
打印文本FATAL ERROR:
。由于简洁是一种美德,它可能会
最好完全跳过log
函数。大声报告错误;成功
静默。