linux清除日志命令
直接说结论:Linux下清除日志,除日最干净利落的志命命令是 truncate -s 0 /var/log/xxx.log,而不是除日很多人习惯的 rm 加 touch。后者会改变文件的志命inode,如果进程还开着这个日志文件,除日空间不会立刻释放,志命得重启服务才行。除日我吃过这个亏——有次线上磁盘爆了,志命手快删了 nginx/access.log,除日结果 df -h 一看,志命空间纹丝不动,除日服务没重启,志命文件句柄还挂在进程上。除日
那为什么 truncate 更稳?志命它把文件大小直接截断为0,inode不变,除日进程继续往里写也没问题。命令简单:
truncate -s 0 /var/log/syslog
或者用 : > /var/log/syslog,效果一样,但后者依赖shell的重定向,在某些cron脚本里可能因为权限问题静默失败。我一般写脚本时优先用 truncate,不容易踩坑。
有人问:echo "" > logfile 行不行?行,但会多一个换行符,文件大小变成1字节,看着别扭。追求极致干净就用 truncate 或 : >。至于 cat /dev/null > logfile,老派做法,能用,但多一次IO,没必要。
再聊聊系统日志。/var/log/journal/ 是 systemd 的二进制日志,不能直接 truncate 或 rm。得用 journalctl 自己清理:
journalctl --vacuum-size=100M 保留最近100M,journalctl --vacuum-time=7d 只留7天。我见过有人直接删 /var/log/journal 下的文件,结果 journald 重启后索引错乱,还得手动 systemctl restart systemd-journald。别那么干。
对于 /var/log/ 下那些 .1、.gz 轮转文件,直接 rm 没问题,因为它们不再被进程写入。但注意别删正在写的那个——比如 messages 和 messages-20240101,后者可以删,前者得 truncate。我习惯用 find /var/log -name "*.gz" -delete 批量清压缩包,省事。
还有个坑:logrotate 配置里如果写了 copytruncate,它会先复制再清空原文件。手动清日志时,如果 logrotate 正在跑,可能冲突。我一般先 systemctl stop logrotate.timer 再操作,完事再启动。不过大多数时候没这么讲究,除非你日志量特别大、轮转特别频繁。
权限问题也常遇到。普通用户对 /var/log/syslog 没写权限,truncate 会报 Operation not permitted。加 sudo 就行。但别用 sudo rm 去删系统日志,万一删了 /var/log/lastlog 或 wtmp,下次 last 命令就废了。这些文件记录登录信息,不是普通文本日志,清之前查清楚。
我自己的清理脚本长这样:
#!/bin/bash
for f in /var/log/nginx/*.log; do truncate -s 0 "$f"; done
journalctl --vacuum-time=3d
find /var/log -name "*.gz" -mtime +7 -delete
跑之前先 df -h 看下空间,跑完再确认。别小看这几行,比网上那些花哨的 echo > 循环靠谱。
最后提一句:清日志不是目的,控制日志量才是。logrotate 配好 size、rotate、compress,比事后手动清强得多。我见过一个服务每秒写几十MB日志,运维天天手动 truncate,后来改成 logrotate 每小时轮转加压缩,磁盘再没爆过。命令是工具,别当日常。