在写入日志语句之前对其进行过滤

在写入日志语句之前对其进行过滤

我有一个应用程序需要在详细模式下运行才能获取我感兴趣的信息。这会生成一个巨大的日志文件,对于我的要求来说,该文件的兴趣<1%。我想要某种方式只记录我感兴趣的那些语句在。

该命令接受一个日志文件名称,将其日志写入其中。它作为 systemd 服务运行。

在将日志写入语句写入磁盘之前,如何拦截并选择它们?

我尝试为 fifo 提供一个文件名,并通过 python 脚本读取该文件名,但这太麻烦了。

答案1

我尝试为 fifo 提供一个文件名,并通过 python 脚本读取该文件名,但这太麻烦了。

这就是至少毛茸茸的选择。每种合理的方法都涉及通过流过滤器工具管道输出,无论是使用 Python 脚本还是使用grepsyslog-ng 手动完成。过滤器需要做的就是从输入中读取一行,然后将其写入输出或不写入。

可以 LD_PRELOAD 对库函数(例如 fwrite() 或 syslog())执行过滤的库,但它仅适用于以下程序:使用libc 提供的函数;许多语言运行时不使用 libc fwrite() (例如 Golang 有自己的 stdio),并且 LD_PRELOAD 对静态链接的可执行文件没有影响。

虽然可以通过使用 ptrace() 或 eBPF 甚至 FUSE 在操作系统级别拦截 write() 系统调用来避免这种情况,但这只会更麻烦,因为文件写入通常由程序缓冲 - 你没有一个每行 write() ,每个 8k 缓冲区有一次 write() 调用,这通常会跨越多行,从一行中间开始等。例如,单个 write() 调用可能包含七行半,所以如果你拦截了它,你不能只是接受/丢弃整个调用,你需要分割并重新组装缓冲区以仅保留你需要的行,保持调用之间的状态来处理分割行,所有这些Python为你做了。

(这意味着,即使 systemd 确实使用 seccomp 和 eBPF 来做某些事情,你也不会找到一个 systemd 参数来神奇地从文件中过滤掉一些数据——不是 stdout/stderr,而是程序本身打开的文件——写入 systemd 绝对有不参与。)

相关内容