避免日志处理中的 bash 缓冲问题

避免日志处理中的 bash 缓冲问题

我的 bash 缓冲问题类似于这里可以找到的问题:关闭管道中的缓冲

上述问题中的 socat 解决方案非常有趣,因为我可以在 initrd dracut 挂钩脚本中访问此命令,不幸的是我不知道如何将其应用于我的特定问题:“实时”解析journalctl json输出(避免缓冲;当journalctl输出它时处理每一行(每个\n)。

logmessage() 函数仅在缓冲区已满时调用;不是在打印新的日记帐行时。不知道问题是在jq之前还是在“< <(”重定向中。

(logmessage() 是一个简单的函数,它将消息写入日志文件和我的普利茅斯控制台)。

在下面的代码中,缓冲区仅在已满时才进行处理,这对我来说没有用。

{
        SEVERITY=( emerg alert crit err warning notice info debug )
        FACILITY=( kern user mail daemon auth syslog lpr news uucp cron authpriv ftp ntp security console cron local0 local1 local2 local3 local4 local5 local6 local7 )
        while read LOG_FACILITY LOG_SEVERITY LOG_TAG LOG_MESSAGE
        do
                logmessage ${FACILITY[$LOG_FACILITY]}.${SEVERITY[$LOG_SEVERITY]} "$LOG_TAG" "$LOG_MESSAGE"
        done < <( journalctl --follow -o json --no-pager --no-tail | jq -r '"\(.SYSLOG_FACILITY // 3) \(.PRIORITY // 6 ) \(.SYSLOG_IDENTIFIER // "journald") \(.MESSAGE | sub("\\n";" ";"g") // "no message")"' )
}&

此代码是特殊 initramfs 的一部分。我有 socat 命令可用。我需要实时解析日志并将设施、优先级、标签和消息发送到不同的目的地(日志文件、普利茅斯控制台插件等)

任何提示将非常感谢。 (此代码将成为 systemimager 软件 (GPL) 的一部分) https://github.com/finley/SystemImager/wiki

任何提示将不胜感激。

答案1

我不确定使用<(...)管道而不是管道可以获得什么:

journalctl ... |
jq -r ... |
while read LOG_FACILITY LOG_SEVERITY LOG_TAG LOG_MESSAGE
do logmessage ...
done

当然,两个版本都有相同的缓冲问题。

但是,在任何一种情况下,如果您想用来socat运行该jq命令,您可以通过替换jq -r ...

socat -u EXEC:'jq -r ...',pty,ctty STDIO

但是有一个大问题,必须引用参数jq,因为这socat会稍微弄乱它们,并且很难正确地传递字符串。解决这个问题的一种方法是将命令保存在 shell 变量中,然后在以后使用它:

export cmd="$(cat <<\! 
jq -r '"\(.SYSLOG_FACILITY // 3) \(.PRIORITY // 6 ) \(.SYSLOG_IDENTIFIER // "journald") \(.MESSAGE | sub("\\n";" ";"g") // "no message")"'
!
)"

socat -u SYSTEM:'eval $cmd',pty,ctty STDIO

但最后,这一切都不是必要的,因为jq选择一个--unbuffered即可达到预期效果的选项。

相关内容