我一直在关注一些类似的问题(例如如何将变量设置为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)格式,但我也尝试过使用backticks。
在我的日志文件中,当出现故障时,我看到的只有:
致命错误:无法删除原始文件,输出为:\n
此外,失败命令的输出会像往常一样出现在屏幕上。我的cmd_output变量保持为空是否有一个共同的原因?
您必须包含特殊标准错误输出流的输出:
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
变量放在双引号之间,以防它包含空格字符。
希望这能有所帮助
*nix命令通常有两种输出形式:标准输出(stdout
)和标准错误(stderr
)。
FOO=$(...)
仅捕获stdout
,而使stderr
不受阻碍。
如果您想要使用此语法的stderr
的内容,则需要使用2>&1
对命令进行后缀,以便将stderr
合并到stdout
中。(例如:rm $file 2>&1
)
由于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
这与原始代码之间的唯一区别是它没有打印文本CCD_ 17。既然简洁是一种美德,那很可能最好完全跳过CCD_ 18函数。大声报告错误;达到目的默默地。