首页 > 解决方案 > can't read logger message thru socat -u UNIX-RECV:/dev/log,ignoreeof - 因为没有新行

问题描述

我正在尝试使用 socat 在 bash 中模拟 syslogd,不幸的是,记录器在发送消息后不会向 /dev/log 发送换行符(它发送 eof)

是否可以选择 ingnoreeof 并将其转换为换行符(crlf 或任何让 bash 阅读愉快的东西)。

我正在尝试socat | 而读 -r LINE 做;对待$LINE;完成但读取块,因为它没有看到换行符。

现在,我有一个自定义的 logmessage 命令,可以在我需要的地方显示我的消息(控制台、普利茅斯特殊皮肤、远程系统日志……),不幸的是,我错过了通过命令和其他东西发送到 /dev/log 的所有消息。使用 socat 方法在 /dev/log 上模拟 syslogd 可以让我获取所有消息,包括重要消息(kmsg 除外,这是另一个故事)...

(/dev/log 还不存在(我在 cmdline 挂钩的 initrd 中)

socat UNIX-RECV:/dev/log,ignoreeof STDOUT | while read -r LINE
do
    echo "Parsing $LINE" > /tmp/debug.txt
done&

logger -p local0.info -t systemimager "My test message"

执行 strace logger 和 strace socat 证明消息已正确发送,但问题是读取命令将永远不会无限期地等待我们忽略的 eof,否则 socat 进程将退出......

(因为读取块,调试文件保持为空)

如果我做:

socat UNIX-RECV:/dev/log,ignoreeof CREATE:/tmp/buffer.log&
tail -f /tmp/buffer.log | while read -r LINE
do
    echo "Parsing $LINE" > /tmp/debug.txt
done&

logger -p local0.info -t systemimager "My test message"

我有完全相同的行为,虽然我可以看到记录器发送的所有消息都被一个接一个地添加到 /tmp/buffer.log 文件中,中间没有任何换行符......

我在一个 centos-6 特制的 initrd 中(systemimager imager https://github.com/finley/SystemImager/wiki/ScreenShots

Centos-6 在它的 initrd 中缺少 rsylogd,所以我需要编写一个用于我的日志调度程序的简约日志,它将消息发送到控制台、普利茅斯日志查看器和远程 xml 记录器(并最终发送到远程 syslogd)

(在基于 systemd 的系统上, journald 正在运行,所以我在 while read -r LINE 之前使用了 journalctl 命令,当然它可以工作)。

我想尽可能避免在收到的每个日志中产生大量进程。

理想情况下,当 socat 收到 EOF 时,发送换行符而不是退出将是完美的。

标签: readlineeofsyslogsocat

解决方案


您可以做的是从 socat 捕获调试输出,因为这包括接收到的数据字节数。然后,您可以让 shell 准确读取该数量的字符。例如,

socat -v -u UNIX-RECV:/dev/log,ignoreeof OPEN:/dev/null 2>&1 |
while read sign date time len from to
do      len=${len##*=}
        read -n "$len" -r LINE
        echo "Parsing $LINE"
done

socat -u用于单向数据流,因此我们可以 OPEN/dev/null作为输出文件。-v写入调试到我们重定向到管道的 stderr 。每个输入记录的典型输出采用标题行的形式(以 开头>和结尾\n):

 > 2019/08/07 21:53:42.951165  length=50 from=0 to=49

接下来,在本例中,您需要捕获 50 个字节的接收数据。上面的while循环读取标题行,拆分单词,以便变量len保存length=50字符串。然后将其减少为仅保留 number 50,并使用选项完成第二次读取,该选项-n在那么多字符之后停止读取。


推荐阅读