清理 Nginx 旧日志是一个常见的运维操作,但有一个非常重要的“坑”需要注意:千万不要直接删除正在被 Nginx 写入的日志文件(如 access.log 或 error.log),否则文件虽然在硬盘上消失了,但 Nginx 进程依然占用着该文件的句柄,磁盘空间不会释放,且日志会停止记录(或写入到一个被删除的匿名文件中)。
以下是清理 Nginx 日志的正确方法,分为临时手动清理和长期自动清理两种。
如果你已经用 rm 删了 access.log 且发现磁盘还是 100%,请立即执行以下命令让 Nginx 重新打开日志文件:
nginx -s reopen
# 或者找到 nginx 的 master 进程号发送 USR1 信号
# kill -USR1 $(cat /var/run/nginx.pid)
执行后,Nginx 会新建日志文件,磁盘空间就会立刻释放。
通常日志系统会自动把旧日志重命名为 access.log.1、access.log.2.gz 等。这些文件 Nginx 已经不再写入,可以直接放心删除:
# 进入日志目录(路径可能不同,一般为 /var/log/nginx)
cd /var/log/nginx
# 查看哪些日志占用了空间
du -sh *
# 删除已经被切割压缩的旧日志(请根据实际情况谨慎操作)
sudo rm -f /var/log/nginx/access.log.*
sudo rm -f /var/log/nginx/error.log.*
如果你想清空当前正在被写入的日志,有两种安全做法:
做法 A:直接截断文件(清空内容,但保留文件本身,推荐)
sudo truncate -s 0 /var/log/nginx/access.log
sudo truncate -s 0 /var/log/nginx/error.log
(注:truncate -s 0 会把文件大小设为 0,但文件 inode 不变,Nginx 会继续往里面写,最安全最方便。)
做法 B:重命名后通知 Nginx 重新建文件(标准切割法)
# 1. 把当前日志改个名字备份
sudo mv /var/log/nginx/access.log /var/log/nginx/access.log.bak
# 2. 通知 Nginx 重新打开日志文件(它会自动创建一个新的 access.log)
sudo nginx -s reopen
# 或者用 kill 发送 USR1 信号: sudo kill -USR1 $(cat /var/run/nginx.pid)
# 3. 现在可以放心处理备份文件了(压缩或删除)
sudo rm -f /var/log/nginx/access.log.bak
在 Linux 系统中,最标准的做法是使用系统自带的 logrotate(日志轮转工具)。大多数发行版(如 Ubuntu、CentOS)在安装 Nginx 时,已经自动生成了配置文件。
cat /etc/logrotate.d/nginx
你通常会看到类似下面的配置:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
[ -s /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
daily / weekly:每天 / 每周轮转一次(也可以改成 size 100M 表示超过 100M 才轮转)。rotate 14:只保留最近 14 份旧日志,超过天数的会自动删除(这就是自动清理旧日志的核心)。compress / delaycompress:对旧日志进行 gzip 压缩以节省空间。postrotate ... kill -USR1 ...:轮转后向 Nginx 发送信号,让其重新打开日志(避免上面提到的“坑”)。如果你希望日志只保留 7 天,把 rotate 14 改成 rotate 7 即可。修改保存后,logrotate 会在第二天自动按新规则执行。
如果你想立刻看到效果,可以强制执行一次:
# 调试模式(只模拟,不真正删文件,看看会发生什么)
sudo logrotate -d /etc/logrotate.d/nginx
# 强制立即执行一次轮转
sudo logrotate -f /etc/logrotate.d/nginx
sudo truncate -s 0 /var/log/nginx/access.log 清空当前日志。/etc/logrotate.d/nginx 里的 rotate 天数,让它自己干就行。