非常大的日志文件,我该怎么办?

(这个问题涉及到一个类似的问题,但它讨论的是一个旋转的日志文件。)

今天我收到了一个关于/var空间非常低的系统消息。

像往常一样,我执行了sudo apt-get clean命令,情况只有稍微改善。然后我删除了旋转的日志文件,但改善的效果也很小。

经过检查,我发现/var/log目录下的一些日志文件变得非常巨大。具体来说,ls -lSh /var/log命令显示:

total 28G
-rw-r----- 1 syslog            adm      14G Aug 23 21:56 kern.log
-rw-r----- 1 syslog            adm      14G Aug 23 21:56 syslog
-rw-rw-r-- 1 root              utmp    390K Aug 23 21:47 wtmp
-rw-r--r-- 1 root              root    287K Aug 23 21:42 dpkg.log
-rw-rw-r-- 1 root              utmp    287K Aug 23 20:43 lastlog

正如我们所看到的,前两个是有问题的。我对为什么这样大的文件没有被轮换感到有些惊讶。

那么,我应该怎么做呢?只需删除这些文件然后重新启动吗?还是采取更谨慎的步骤?

我正在使用Ubuntu 14.04。

更新1

首先,系统只有几个月的历史。几个月前,我的硬盘崩溃后,我不得不从头安装系统。

现在,根据this answer的建议, 我首先使用tail检查了有问题的日志文件,这并不令人意外。然后,为了进行更深入的检查,我执行了来自same answer的脚本。

for log in /var/log/{syslog,kern.log}; do 
  echo "${log} :"
  sed -e 's/\[[^]]\+\]//' -e 's/.*[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}//' ${log} \
  | sort | uniq -c | sort -hr | head -10
done

整个过程花了几个小时的时间。 输出结果如下所示,
/var/log/syslog :
71209229  Rafid-Hamiz-Dell kernel:  sda3: rw=1, want=7638104968240336200, limit=1681522688
53929977  Rafid-Hamiz-Dell kernel:  attempt to access beyond end of device
17280298  Rafid-Hamiz-Dell kernel:  attempt to access beyond end of device
   1639  Rafid-Hamiz-Dell kernel:  EXT4-fs warning (device sda3): ext4_end_bio:317: I/O error -5 writing to inode 6819258 (offset 0 size 4096 starting block 54763121030042024)
       <snipped>

/var/log/kern.log.1 :
71210257  Rafid-Hamiz-Dell kernel:  attempt to access beyond end of device
71209212  Rafid-Hamiz-Dell kernel:  sda3: rw=1, want=7638104968240336200, limit=1681522688
   1639  Rafid-Hamiz-Dell kernel:  EXT4-fs warning (device sda3): ext4_end_bio:317: I/O error -5 writing to inode 6819258 (offset 0 size 4096 starting block 954763121030042024)

(/dev/sda3 是我的主目录。正如我们所知,

lsblk /dev/sda
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 931.5G  0 disk 
├─sda1   8:1    0 122.1G  0 part /
├─sda2   8:2    0   7.6G  0 part [SWAP]
└─sda3   8:3    0 801.8G  0 part /home
为什么一个进程会想要超出限制去写入,这实际上超出了我的理解范围。如果即使在系统更新后这种情况仍然持续下去,也许我会在这个论坛上提出一个不同的问题。
然后,从这个答案(你可能想要查看这个链接以获得更深入的理解),我执行了,
sudo su -
> kern.log
> syslog

现在,这些文件的大小为零。系统在重启前后都运行正常。
接下来几天我会观察这些文件(以及其他文件),如果它们表现异常,我会及时报告。
最后需要注意的是,这两个有问题的文件(kern.log和syslog)已经设置了轮转,通过检查/etc/logrotate.d/目录下的文件(使用grep命令可以帮助)可以看到。
更新2:
日志文件实际上已经进行了轮转。看起来这些大文件大小是在一天内产生的。

2那些日志文件中有没有任何线索,能解释为什么它们这么大?删除并重新启动,然后监控它们,看它们是否以某种指数方式增长。 - douggro
@douggro 确实有的。请查看我对问题的更新。 - Masroor
1我遇到了这个问题,原因是有很多后台运行的docker容器。 - Bhaskar
4个回答

只需删除这些文件然后重新启动吗?
不,清空它们但不要使用rm命令,因为在您输入touch命令重新创建文件时可能会导致某些程序崩溃。
最简单的方法:
cd /var/log
sudo su
> lastlog
> wtmp
> dpkg.log 
> kern.log
> syslog
exit

如果不是root用户,将需要使用sudo命令。这段话摘自AU上的另一个答案
在你执行之前,请先执行tail {logfile}命令,并检查是否有原因导致文件变得如此庞大。除非这个系统已经运行了好几年,否则不应该出现这种情况,解决问题比任其继续更好。
kern.log和syslog通常不会那么大。但是像我说的,如果这个系统已经运行了多年,那可能是正常的,只需要清理一下文件即可。
为了防止将来再次变得如此庞大,请设置logrotate。它非常简单,当日志文件达到你设定的大小时,它会自动压缩日志文件。
还有一件事:如果您不想删除内容,可以通过打包或压缩文件来压缩它们。这样您最终可能会得到现在文件大小的10%左右。前提是磁盘上还有足够的空间来执行此操作。

7wtmp: 命令未找到。这是哪个软件包? - Janus Troelsen
/var/log/wtmp不是一个命令,而是一个日志文件。我的回答中哪里说你可以执行wtmp了呢?;-) - Rinzwind
14我以为>是一个提示符,所以尝试了"lastlog"命令,结果成功了。因此我认为自己理解得没错 :P - Janus Troelsen
这个问题一直在发生。我正在使用Ubuntu 16.04。你能告诉我是什么原因导致了这个问题吗?提前谢谢! - Gayan
I/O错误通常与硬件有关,可能是故障的电缆、故障的硬盘或者故障的文件系统。"尝试访问设备末端之外"似乎很严重。 - Rinzwind
@Gayan 嗨!我刚看了你在原问题中提供的错误信息。看起来好像是有东西写入到了同一个inode,6819258。请检查一下在你的16.04版本中是否是相同的inode。无论它是否相同,考虑一下这个inode所属的文件是什么,可以参考这里中的几种方法来进行检查。也许检查一下正在被写入的文件会对问题的原因有所启示。另外,不要忽视Rinzwind的建议 - 这可能与硬件有关。 - Sergiy Kolodyazhnyy
@Gayan 你曾经进行过文件系统检查吗?执行 sudo touch /forcefsck 并重新启动。这将启动一个文件系统检查 :) - Rinzwind
我实际上在使用touch重新创建/var/log/syslog时遇到了问题,就像你所警告的那样。对于这个迟来的教训给你一个赞! - WinEunuuchs2Unix
很遗憾,这个解决方案在Ubuntu 18.04上不起作用。 - Luís de Sousa
那么你一定做错了什么。由于这些是核心的Linux工具,它们几乎适用于任何Linux系统 :) - Rinzwind
21这个答案没有充分描述你应该如何处理lastlog、wtmp、dpkg.log、kern.log和syslog文件。 - Tor Klingberg
@TorKlingberg 这不是问题的关键,因此答案确实没有反映出这一点。 - Rinzwind
1@TorKlingberg 感谢你的评论,我花了一些时间才理解这个……你可以通过执行> logfilename来清空日志文件,就像这里所解释的那样。 - Chagai Friedlander
2我记不起两年前我在评论中的意思了,但显然还有其他15个人同意,所以我猜它就这样吧。也许我当时没有理解">"符号是将内容重定向到文件中,而不是作为提示符。 - Tor Klingberg

可能值得尝试确定填充日志的内容 - 可以通过使用lesstail命令进行目视检查来实现。
tail -n 100 /var/log/syslog

如果冒犯的行为太深埋,难以轻易看清发生了什么,可以使用类似这样的表达方式。
for log in /var/log/{dmesg,syslog,kern.log}; do 
  echo "${log} :"
  sed -e 's/\[[^]]\+\]//' -e 's/.*[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}//' ${log} \
  | sort | uniq -c | sort -hr | head -10
done

请注意:由于文件较大,这可能需要一些时间。它将尝试去除时间戳,然后计算出现频率最高的消息。

我的清理系统日志文件的方法是这样的。步骤1和2是可选的,但有时你需要检查旧日志,并且备份有时也很有用。;-)
1. 可选:复制日志文件 ``` cp -av --backup=numbered file.log file.log.old ```
2. 可选:对日志副本使用 Gzip ``` gzip file.log.old ```
3. 使用 /dev/null 清空文件 ``` cat /dev/null > file.log ```
我们使用日志轮转(logrotate)来处理这些日志(仅在几台服务器上),并且每周通过cron脚本执行,将所有以*.1(或下一个轮转)结尾的文件压缩成gzip格式。

1这是在Ubuntu 18.04上的正确方法。 - Luís de Sousa
这应该是被接受的答案。当日志迅速填满(尽管进行了日志轮转)时,说明存在某种内在问题,值得进一步深入挖掘。 - Sudip Bhandari

今天我安装了Ubuntu 16.04,发现了同样的问题。不过,我通过busybox-syslogd解决了这个问题。是的!我刚刚安装了那个软件包,问题已经解决了。:)
$ sudo apt-get install busybox-syslogd

安装完该软件包后,重置syslogkern.log
sudo tee /var/log/syslog /var/log/kern.log </dev/null

希望这个简单的解决方案对其他人有所帮助。

5这个包具体是做什么的,以及这个解决方案是如何工作的? - Aaron Franke
2我对这篇帖子持怀疑态度,因为这些文件不可能在一天之内变得如此庞大。所以在听到其他人对这个程序的意见之前,我会暂时搁置。 - SDsolar