1

我编写了一个大型 Bash 程序,该程序由几个在深层目录树中组织的 shell 脚本组成。该程序很复杂,拥有熟练的调试和日志记录基础设施至关重要。在其中一个子脚本中,我编写了一个记录器函数,该函数能够接收日志消息并将这些消息路由到适当的 MySQL 表。

logger 函数有一个简单的输入接口,它只接受一个参数,即日志消息,并且可以想象成一个特殊版本的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一个简单的解决方案可以沿着log. 但是,我需要将日志消息存储在数据库中而不是文件中。

此外,exec似乎与管道重定向不兼容,例如exec | log_f. (修改 log_f 以支持标准输入)。我能想到的唯一丑陋的解决方案是在调用期间设置整个脚本的重定向,例如:

# I am a starter of sub-scripts
a_script_in_the_tree.sh 2>&1 | log_f

但是,最好让每个脚本在内部管理自己的日志记录方法,使用它自己的一组在其范围内可用的函数。

4

2 回答 2

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

和俗气的读者

$ 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
于 2013-10-03T00:55:38.670 回答
0

刚从我脑海里冒出来:

exec > >(log_f) 2>&1
于 2013-10-03T13:24:29.333 回答