我花了几天时间编写了一个 python 脚本,并为其创建了一个 systemd 单元文件。在测试过程中,脚本向日志记录了很多错误。现在我已经完成了,我想从日志中清除这些错误。
有多种方法可以清除整个日志,如下所述:如何清除journalctl
包括 using journalctl --vacuum-time=2d
、 usingjournalctl --vacuum-size=500M
和临时SystemMaxUse=
在 /etc/systemd/journald.conf 中设置为非常低的值。
所有这些似乎都会清除整个日志,影响所有单位。我只需要清除单个单元的条目。这可能吗?
答案1
使用我的 Python 3 程序复制日志.py/var/log/journal
在要从中删除条目的日志文件上。
system.journal
例如,要制作没有日志条目的副本NetworkManager.service
:
$ journalctl --file=system.journal | wc
167 1934 18825
$ journalctl --file=system.journal | grep -v NetworkManager | wc
77 881 8421
$ python3 copy_journal.py --remove-unit=NetworkManager.service system.journal system-without-nm.journal
$ journalctl --file=system-without-nm.journal | wc
77 881 8421
答案2
我正在寻找一种从 systemd 日志中删除特定消息的方法。这似乎并不罕见(例如,意外运行错误的命令或有大量垃圾邮件)。
通过修改现有文件来编辑特定条目似乎是不可行的,因为systemd 日志格式主要设计用于支持附加,其中涉及可选的压缩、散列、更新计数器、对偏移量和散列的索引引用。我一开始尝试过这个,但不建议任何人这样做。
要删除特定条目,我发现下一个最好的办法是根据现有日志文件生成一个新的日志文件(例如来自的 Python 脚本)另一个答案做这个)。Systemd 实际上提供了轻松修改日志条目所需的工具利用这个原理。
简洁版本
本质上,将日志导出为文本格式,然后将其转换回日志:
journalctl --file=system.journal -o export | /lib/systemd/systemd-journal-remote --output=result.journal
通过将初始输出通过管道传送到程序/脚本(例如 awk、sed 等)以在将其传送到systemd-journal-remote
.
更手动的方法是将文本写入文件,使用文本编辑器手动修改文件,然后将其转换回文件.journal
。下面对此进行更详细的解释。
长版
这是较长的版本,是修改现有日志的分步指南(在 ArchLinux 上测试,使用 Ubuntu live USB,systemd 246)。
首先,确保日志已关闭。例如,关闭计算机。
启动不同的设备(例如通过可启动的实时 USB)。这是为了能够进行更改而不会无意中影响期刊。
为了最大限度地减少意外副作用,请将原始磁盘安装为只读。例如:
$ sudo mount -o ro /dev/sda1 /mnt
另一个例子,如果您使用 LUKS 加密设备:
$ sudo cryptsetup luksOpen /dev/sda1 whateverName $ sudo mount -o ro /dev/mapper/whateverName /mnt
如果您当前的设备没有 systemd/journalctl,请使用 chroot 以便能够使用只读磁盘中的二进制文件。使其正常工作的最低要求如下:
$ sudo mount --bind /tmp /mnt/tmp $ sudo mount --bind /tmp /mnt/var/tmp $ sudo mount -t proc /proc /mnt/proc $ sudo chroot /mnt
准备好后,导出日志。
$ journalctl --file=system.journal -o export > /tmp/export.txt
编辑导出以编辑、添加、修改或删除条目。如果您愿意,您可以在 chroot 之外执行此操作,例如使用
vi -b /tmp/export.txt
.
输出示例:https://www.freedesktop.org/wiki/Software/systemd/export/进行所需的修改后,使用 将其转换回日记帐
systemd-journal-remote
。该二进制文件不在 bin / 中$PATH
,因此您需要使用程序位置的绝对路径:$ /lib/systemd/systemd-journal-remote --output=/tmp/result.journal /tmp/export.txt
验证日志是否具有所需的输出,例如通过使用以下命令对日志进行分页:
$ journalctl --file=/tmp/result.journal
如果您满意,请继续下一步。否则从步骤 6 开始重复。
如果需要,退出 chroot(CtrlD或简单地
exit
)并撤消步骤 4:$ sudo umount /mnt/proc $ sudo umount /mnt/tmp $ sudo umount /mnt/var/tmp
现在我们即将覆盖原始日志。
如果您已将该卷安装为只读(步骤 3),请重新安装为可写。$ sudo mount -o remount,rw /mnt
为了避免文件属性或所有权发生不必要的更改,只需替换内容而不是复制文件。
# cat /tmp/result.journal > /mnt/var/log/journal/MACHINE_ID_HERE/system.journal
或者,如果您没有在 root shell 中运行,请使用
sudo tee outfile >/dev/null
,如下所示:$ </tmp/result.journal sudo tee /mnt/var/log/journal/MACHINE_ID_HERE/system.journal >/dev/null
如果需要,卸载磁盘(来自步骤 3/步骤 10)。
$ sudo umount /mnt
如果您已打开加密卷(在步骤 3 中),请再次锁定它:
$ sudo cryptsetup luksClose whateverName
答案3
我在这里复制了我的答案stackoverflow 上重复的问题
我找不到可能的具体版本,journaltcl 文档甚至没有提到 --vacuum-time (或 -size 或 -files)可以与 --unit 组合,但我有 ver:249,真空清理来了在版本:218 中,单位过滤器在版本:195 中出现。
TLDR:不再需要旧的和迂回的方法:
要清理一个单元的所有日志:
journalctl --vacuum-time=1s --unit=your.service
如果您不介意旋转其他所有日志,并且仍然找到来自您的设备的日志(意味着它的最后一个日志尚未旋转),您可以一次性旋转:
journalctl --rotate --vacuum-time=1s --unit=your.service
答案4
我不认为这是可能的,因为根据journalctl手册页“输出是从所有可访问的日志文件中交错的,无论它们是轮换的还是当前正在写入的”。
但是,您可以按单位“journalctl -u some.service”对其进行过滤,然后尝试使用 cron 使用您自己的脚本从日志中删除日志条目。