我写了一个很大的Bash程序,它由在深度目录树中组织的几个shell脚本组成。该程序很复杂,具有熟练的调试和日志记录基础结构是至关重要的。 在其中一个子脚本中,我编写了一个记录器函数,它能够接收日志消息并将它们路由到适当的MySQL表。
记录器函数有一个简单的简单输入接口,它只接受一个参数,即日志消息,可以想象为echo
内置函数的特殊版本,它直接打印到数据库中,并确定路由内部。
在代码中,这转换为:
# generic code, somewhere in the program
if success; then
log_f "Previous function returned success"
else log_f "Previous function returned failure"
fi
这种方法的缺点是只能记录那些明确意味着通过log_f
的消息;也就是说,外部二进制文件或Bash本身生成的任何错误消息都不会保存在数据库中。
一个简单的解决方案可以沿着exec >log 2>&1
行,它将从stdin和stderr输出的所有内容都注册到log
。但是,我需要将日志消息存储在数据库中而不是存档。
此外,exec
似乎与管道重定向不兼容,例如exec | log_f
。 (log_f已修改为支持stdin)。
我能想到的唯一解决方案是丑陋,它是在调用期间设置整个脚本的重定向,例如:
# I am a starter of sub-scripts
a_script_in_the_tree.sh 2>&1 | log_f
但是,最好让每个脚本在内部管理自己的日志记录方法,使用其范围内可用的自己的一组函数。
答案 0 :(得分:1)
一个简单的解决方案可以沿
行走exec >log 2>&1
命名管道可以取代日志文件,尽管这需要一个fifo-to-sql进程来使用输出并将其发送到数据库。这将使您“自我依赖”每个脚本重定向,同时增加每个脚本启动幂等消费者所需的负担。这对另一个人来说是一种丑陋吗?
这是一对简单的脚本,用于演示这个想法,即需要记录服务的脚本:
$ cat nplog.sh
#!/bin/bash
logfifo=/tmp/log.fifo
if [ ! -p $logfifo ]; then
# should maybe spawn npreader here
echo logging system is not running: $logfifo does not exist 1>&2
exit 1
fi
exec > $logfifo 2>&1
while true; do
date
cat /does.not.exist
sleep 1
done
和cheezy读者
$ cat npreader.sh
#!/bin/bash
# oversimplified for illustration. should remove the fifo upon exit so
# that clients can't attach when reader is down
logfifo=/tmp/log.fifo
mkfifo $logfifo
cat $logfifo
答案 1 :(得分:0)
刚从脑子里出来:
exec > >(log_f) 2>&1