我的 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
即可达到预期效果的选项。