13 10 月 2026

日志是排查问题的唯一依据,但它也是磁盘的头号杀手。不管理的话,几个月就能把一个 40G 的系统盘写满。

这篇讲:Linux 有哪些日志、怎么看、怎么自动轮转清理、以及出问题时怎么快速定位。

日志和备份是运维的两条命脉。财富云计算 的云服务器支持快照与扩容;内网服务、游戏服务端可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。

一、Linux 有哪些日志

systemd 系统(现代发行版)

用 journalctl 统一管理:

journalctl                           # 全部日志
journalctl -b                        # 本次开机以来
journalctl -b -1                     # 上一次开机(排查崩溃原因)
journalctl -f                        # 实时跟踪
journalctl -u nginx                  # 某个服务
journalctl -u nginx -f               # 实时跟踪某服务
journalctl -u nginx --since today
journalctl --since "2026-10-01" --until "2026-10-02"
journalctl -p err -n 50              # 只看错误级别
journalctl -k                        # 内核日志(等同 dmesg)
journalctl --disk-usage              # 日志占了多少空间
journalctl -o json-pretty            # JSON 输出

日志级别:emerg(0) alert(1) crit(2) err(3) warning(4) notice(5) info(6) debug(7)

传统文本日志

路径内容
/var/log/syslog系统综合日志(Debian/Ubuntu)
/var/log/messages系统综合日志(CentOS)
/var/log/auth.log登录认证日志(Ubuntu)
/var/log/secure登录认证日志(CentOS)
/var/log/kern.log内核日志
/var/log/dmesg启动信息
/var/log/nginx/access.logNginx 访问日志
/var/log/nginx/error.logNginx 错误日志
/var/log/mysql/error.logMySQL 错误日志
/var/log/php8.2-fpm.logPHP-FPM 日志
/var/log/fail2ban.logfail2ban 日志
/var/log/cron定时任务日志
/var/log/audit/audit.log审计日志(SELinux)

常用查看方式:

tail -f /var/log/syslog              # 实时跟踪
tail -n 100 /var/log/nginx/error.log
head -n 50 file.log
less file.log                        # 分页,可搜索
grep "error" file.log
grep -i "fail" file.log | tail -20
sed -n '10,20p' file.log             # 看指定行
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head

二、日志为什么会撑爆磁盘

  1. journald 无限制增长(默认上限是磁盘的 10% 或 4GB)
  2. Nginx/Apache 访问日志从不轮转
  3. 程序开 DEBUG 级别,疯狂输出
  4. 错误循环:服务反复崩溃重启,每次都写一堆日志
  5. 没有 logrotate 配置

查看谁占了空间:

du -sh /var/log/* | sort -h
journalctl --disk-usage
ncdu /var/log

三、logrotate:自动轮转清理

logrotate 是 Linux 标准的日志轮转工具,按天/周/大小切分日志、压缩、保留指定份数、删除过期。

配置位置

/etc/logrotate.conf          主配置
/etc/logrotate.d/*           各软件的配置文件(推荐放这里)

配置示例(Nginx)

cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily                    # 每天轮转
    missingok                # 日志不存在不报错
    rotate 14                # 保留 14 份
    compress                 # 压缩旧日志
    delaycompress            # 延迟一轮再压缩(避免服务还占用)
    notifempty               # 空文件不轮转
    create 0640 www-data adm # 新建文件的权限和所有者
    sharedscripts            # 多个日志只执行一次脚本
    postrotate               # 轮转后执行的命令
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}
kill -USR1 是通知 Nginx 重新打开日志文件。不通知的话,Nginx 会继续往已改名的旧文件里写。

常用参数

参数说明
daily / weekly / monthly轮转周期
rotate N保留 N 份
size 100M达到指定大小就轮转(可与 daily 同用,满足任一即触发)
compress用 gzip 压缩
delaycompress延迟一轮压缩
nocompress不压缩
missingok文件不存在不报错
notifempty空文件不轮转
create 权限 用户 组轮转后新建文件的属性
copytruncate复制后清空原文件(适用于不能发信号重开日志的程序)
dateext用日期做后缀,如 access.log-20261013
sharedscripts所有日志处理完才执行一次脚本
postrotate/endscript轮转后执行的命令
prerotate/endscript轮转前执行的命令
su 用户 组指定轮转操作的用户
maxage 30超过 30 天的删除

自己写一个配置

比如给自己的应用 /var/log/myapp/*.log:

nano /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 7
    size 50M
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    dateext
}

copytruncate 的用法:程序不支持重新打开日志文件(无法发信号)时用它。原理是"复制一份再清空原文件",程序继续写原文件不受影响。缺点是可能丢失复制瞬间的少量日志。

测试与手动执行

# 调试模式(不实际执行,只显示会做什么)
logrotate -d /etc/logrotate.d/myapp

# 强制执行一次
logrotate -f /etc/logrotate.d/myapp

# 执行全部配置
logrotate -f /etc/logrotate.conf

# 查看状态记录
cat /var/lib/logrotate/status

先 -d 再 -f,确认无误再让它自动跑。

logrotate 什么时候执行

由 cron 或 systemd timer 触发,通常每天一次:

cat /etc/cron.daily/logrotate
systemctl list-timers | grep logrotate

四、journald 日志限制

journald 默认可能占用几个 GB,必须限制:

nano /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M          # 日志最多占 500M
SystemKeepFree=1G          # 至少保留 1G 给系统
MaxRetentionSec=14day      # 最多保留 14 天
Compress=yes               # 压缩
RateLimitIntervalSec=30s   # 限流(防止日志风暴)
RateLimitBurst=1000
systemctl restart systemd-journald

立即清理:

journalctl --disk-usage              # 看占用
journalctl --vacuum-size=500M        # 清理到 500M
journalctl --vacuum-time=7d          # 只保留 7 天
journalctl --vacuum-files=5          # 只保留 5 个文件

如果不需要持久化日志(省磁盘):

# 改成只存内存
mkdir -p /var/log/journal
# 或编辑 journald.conf:Storage=volatile

五、应用日志的规范建议

1)日志写到统一目录

/var/log/myapp/
├── app.log
├── error.log
└── access.log

不要把日志写到程序目录或 /tmp。

2)按级别分离

错误日志单独一个文件,方便监控和告警:

tail -f /var/log/myapp/error.log

3)控制日志级别

# 生产环境不要开 DEBUG
log_level = info

DEBUG 级别的日志量可能是 INFO 的几十倍。

4)日志格式要结构化

好的日志格式:

2026-10-13 02:50:39 [ERROR] [user=123] [req=a1b2c3] 订单创建失败: 库存不足

包含时间、级别、上下文(用户ID、请求ID),排查时能快速串联。

5)每个服务配 logrotate

新装一个服务就顺手加一条 logrotate 配置,别等磁盘满了再补。


六、实用排查技巧

1)统计错误出现次数

grep -c "ERROR" app.log
grep "ERROR" app.log | wc -l

2)按时间过滤

sed -n '/2026-10-13 02:00/,/2026-10-13 03:00/p' app.log
awk '$1" "$2 >= "2026-10-13 02:00" && $1" "$2 <= "2026-10-13 03:00"' app.log
grep "13/Oct/2026:02:" access.log

3)找访问最多的 IP

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20

4)找最慢的请求

日志格式里加了 $request_time 后:

awk '{print $NF, $7}' access.log | sort -rn | head -20

5)看某个 IP 的访问记录

grep "1.2.3.4" access.log | tail -50

6)实时监控关键字

tail -f app.log | grep --color -E "ERROR|WARN|Exception"

7)多个日志同时看

tail -f /var/log/nginx/access.log /var/log/nginx/error.log

或者用 multitail:

apt install multitail -y
multitail /var/log/nginx/access.log /var/log/nginx/error.log

七、集中化日志(进阶)

服务器多了以后,登录每台看日志太低效。方案:

方案复杂度适合
rsync 汇总到一台低小团队
Loki + Grafana中推荐,轻量,与 Grafana 无缝
ELK(Elasticsearch+Logstash+Kibana)高大团队,功能强但吃资源
云厂商日志服务低付费,省事

Loki 的优势:只索引标签不索引全文,资源占用远低于 ELK,2 核 4G 就能跑。


八、磁盘满了的应急处理

# 1. 看谁占的多
du -sh /var/log/* | sort -h

# 2. 清 journald
journalctl --vacuum-size=200M

# 3. 删旧的轮转日志
find /var/log -name "*.gz" -delete
find /var/log -name "*.1" -delete
find /var/log -name "*-2026*" -mtime +30 -delete

# 4. 清空当前大日志(不删文件,避免程序写失败)
: > /var/log/nginx/access.log
truncate -s 0 /var/log/huge.log

# 5. 立刻跑一次轮转
logrotate -f /etc/logrotate.conf

⚠️ 不要用 rm 直接删正在写入的日志:程序持有句柄,空间不会释放,还会写失败。要用 truncate 或 copytruncate。

# 检查已删除但仍被占用的文件
lsof | grep deleted
# 处理:重启对应服务

九、一份标准的日志配置

journald(/etc/systemd/journald.conf):

[Journal]
SystemMaxUse=500M
MaxRetentionSec=14day
Compress=yes

Nginx(/etc/logrotate.d/nginx):保留 14 天,每天轮转。

自定义应用(/etc/logrotate.d/myapp):

/var/log/myapp/*.log {
    daily
    rotate 14
    size 100M
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    dateext
    maxage 30
}

定时巡检(crontab):

0 4 * * 0 /usr/bin/journalctl --vacuum-time=7d
0 4 * * * /usr/bin/find /var/log -name "*.gz" -mtime +30 -delete

十、常见问题

问题原因解决
轮转后服务不写新日志没发信号通知重开加 postrotate 或改用 copytruncate
日志没被轮转配置路径不对 / 没被 cron 触发logrotate -d 调试
磁盘还是满journald 没限制配 SystemMaxUse + --vacuum-size
权限报错 parent directory has insecure permissions目录属主不对加 su 用户 组 或修正目录权限
日志丢失copytruncate 期间的少量丢失改用 postrotate 发信号
轮转后日志变成空程序没重开文件句柄同上

日志管理做好了,排查问题事半功倍。财富云计算 的云服务器提供完整 root 权限,可自由配置日志策略与监控;内网服务、游戏服务端可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上),适合长期挂服务。

相关阅读:

  • 《crontab 计划任务完全指南》
  • 《服务器资源排查:CPU / 内存 / 磁盘 / 带宽》
  • 《Linux 磁盘挂载与扩容实战》
延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:crontab 计划任务完全指南:定时备份、定时重启、定时巡检
  2. 下一篇:PHP-FPM 安装与性能调优:让 PHP 站点快起来还省内存
发表评论 4

取消回复