是否可以自定义 Bash 错误消息属性?
例如,是否可以编辑.bash_profile
以获取以下 Bash 错误消息
-bash: cd: foo: No such file or directory
红色的?
答案1
遗憾的是,没有PS
提示变量来控制 bash 错误的呈现方式。
标准错误是解决此类问题的全面解决方案,但它如果不进行修改将无法工作,因为它有一个硬编码排除(bash
请继续阅读以了解原因)。此外,它还具有一定的侵入性(DLL 注入)。
希莱特要求您将其用作包装器,这对诸如 bash 内置命令不起作用cd
。
您的问题专门询问了 bash 错误消息,这些消息会发送到stderr
,但stderr
也会与任何子进程(即任何其他命令)共享。我不确定您是否想区分这两者。
这里隐藏的一个问题是,它bash
本身会将提示和你的输入(回显)写入stderr
。为了证明:
bash # start a sacrificial shell
exec 2> tmpfile # change stderr to a file
ls # you will see no prompt, and no command echo
...
exit # quit sacrificial shell
cat tmpfile # contains PS1 prompt, your commands (and any errors too)
内置函数调用(或至少应该调用)builtin_error()
内部函数来打印错误,这会无条件调用fprintf()
,stderr
因此选项很少。
无需费尽心机或打补丁bash
,突出显示错误的一个简单方法是:
function _t_debug()
{
if [ "${BASH_COMMAND:0:6}" != "_t_err" ]; then
_lastcmd="$BASH_COMMAND"
fi
}
function _t_err()
{
local rc=$1 nn _type _argv
#shift; pipe=($*)
#if [ ${#pipe[*]} -gt 1 ]; then
# for ((nn=1; nn<=${#pipe[*]};nn++));do
# rc=${pipe[$((nn-1))]}
# echo -n "[$nn]=$rc ";
# ((rc >=128)) && echo -n "($((rc-128))) "
# done
#fi
read -a _argv <<< ${_lastcmd}
_type=$(type -t "${_argv[0]}")
if [ -n "$_lastcmd" ]; then
tput setf 4
printf 'Error %s: "%s"' "${_type}" "${_lastcmd:-unknown command}"
tput sgr 0
printf "\n"
fi
((rc >=128)) && echo "[rc=$rc ($((rc-128)))]" ||
echo "[rc=$rc]"
}
trap '_t_err $? ${PIPESTATUS[*]}' ERR
trap '_t_debug' DEBUG
这将使用 bash DEBUG
trap 在执行前缓存每个命令行,并使用 trapERR
输出非零的返回代码。但对于某些 bash 内置命令(特别是复合命令:while/case/for/if
以及更多信息,请参阅手册页)。
我在我的 中使用了它的变体.profile
,尽管我使用了pipe[]/PIPESTATUS[]
上面注释掉的部分,但它与上面介绍的 DEBUG 陷阱不兼容。如果您注释掉 ,trap DEBUG
则可以使用它来显示管道中每个命令的返回代码。
(此外,由于它被引用,command_not_found
函数钩子是 bash-4.0+。)
答案2
以下解决方案可以满足您的需要:
# whatever_command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
基本上,上面的命令打印标准错误红色的。
查看下面的屏幕截图:
我不知道如何使它永久生效。但是,这肯定会给你一些提示。
答案3
你可能想看看标准错误以寻求更持久的解决方案。
答案4
也许你可以尝试希莱特-我认为这是最简单的解决方案之一。