为什么要看日志?
有一次网站突然502错误,我急得满头大汗,最后是看日志才发现是MySQL连接数超限。如果早看日志,5分钟就解决了。
日志是服务器的”黑匣子”,几乎所有问题都能从日志里找到线索。
日志文件位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /var/log/ # 主要日志目录 ├── auth.log # 登录日志 ├── syslog # 系统日志 ├── kern.log # 内核日志 ├── messages # 通用消息 ├── nginx/ # Nginx日志 │ ├── access.log # 访问日志 │ └── error.log # 错误日志 ├── mysql/ # MySQL日志 │ └── error.log ├── apache2/ # Apache日志 │ ├── access.log │ └── error.log └── docker/ # Docker日志(可能不在这里)
|
tail - 实时查看日志
tail是查看日志的神器,尤其适合看实时日志。
基本用法
1 2 3 4 5 6 7 8
| tail /var/log/syslog
tail -n 100 /var/log/syslog
tail -f /var/log/syslog
|
故事:有一次我要等一个用户操作,用户说”我点了”,我看不到日志,急得团团转。后来才知道要用 tail -f 实时看,而不是每次都 cat 整个文件。
实时查看多文件
1 2
| tail -f /var/log/nginx/access.log /var/log/nginx/error.log
|
查看特定时间段的日志
1 2
| tail -F -n 200 /var/log/syslog
|
journalctl - systemd日志(推荐)
systemd的日志比传统 /var/log/ 更好,支持查询、过滤,不需要切换不同文件。
基本查询
1 2 3 4 5 6 7 8
| journalctl
journalctl -n 50
journalctl -f
|
查看特定服务
1 2 3 4 5 6 7 8
| journalctl -u nginx
journalctl -u mysql
journalctl _PID=1234
|
时间过滤
1 2 3 4 5 6 7 8 9 10 11
| journalctl --since today
journalctl --since yesterday --until today
journalctl --since "30 minutes ago"
journalctl --since "2024-02-13 10:00" --until "2024-02-13 12:00"
|
优先级过滤
1 2 3 4 5 6 7
| journalctl -p err -p warning
journalctl -p err journalctl -p warning journalctl -p notice
|
只看某个用户的日志
1 2
| journalctl _UID=1000 journalctl _SYSTEMD_USER_UNIT=user@
|
持久化journal日志
默认日志只在内存,重启会丢失。持久化:
1 2 3 4 5 6 7 8
| mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald
|
grep - 搜索日志内容
grep是搜索大王,用它能在海量日志中快速找到问题。
基本搜索
1 2 3 4 5 6 7 8
| grep "error" /var/log/nginx/error.log
grep -E "error|warning" /var/log/syslog
grep "error" /var/log/syslog | grep "database"
|
实时搜索
1 2
| tail -f /var/log/syslog | grep "error"
|
显示行号和上下文
1 2 3 4 5 6 7 8 9 10 11
| grep -n "error" /var/log/syslog
grep -C 2 "error" /var/log/syslog
grep -A 2 "error" /var/log/syslog
grep -B 2 "error" /var/log/syslog
|
忽略大小写
1
| grep -i "Error" /var/log/syslog
|
统计匹配次数
1
| grep -c "error" /var/log/nginx/error.log
|
反向搜索
1 2
| grep -v "error" /var/log/syslog
|
组合拳:常用查询场景
场景1:网站502错误,快速排错
1 2 3 4 5 6 7 8
| tail -n 100 /var/log/nginx/error.log
grep "502" /var/log/nginx/error.log
journalctl --since "10 minutes ago" | grep -E "nginx|mysql|php"
|
场景2:查看谁登录过服务器
1 2 3 4 5 6 7 8
| grep "Accepted" /var/log/auth.log
grep "Failed" /var/log/auth.log
tail -f /var/log/auth.log | grep "Failed"
|
场景3:Docker容器日志
1 2 3 4 5 6 7 8 9 10 11
| docker logs container_name
docker logs -f container_name
docker logs --tail 200 container_name
docker logs --since 2024-02-13T10:00 container_name
|
场景4:排查磁盘爆满
1 2 3 4 5
| find /var/log -name "*.log" -size +100M
du -h --max-depth=1 /var/log | sort -hr
|
日志分析工具推荐
手写grep太累?试试工具:
1. multitail
同时监控多个日志,彩色输出:
1 2 3
| apt install -y multitail
multitail /var/log/nginx/access.log /var/log/nginx/error.log
|
2. lnav
自动解析日志,支持搜索、高亮:
1 2 3
| apt install -y lnav
lnav /var/log/nginx/error.log
|
3. journalctl -o json
输出JSON格式,方便脚本处理:
踩坑经验
坑1:tail -f 不显示新日志
- 可能是日志轮转了(文件被重命名)
- 解决:用
tail -F(大写F)
坑2:journalctl日志太多看不过来
坑3:日志文件太大打不开
- 不要
cat 整个文件,用 tail 或 head
- 或者分割文件:
split -l 1000000
坑4:日志没有时间戳
日志管理最佳实践
1. 定期清理
1 2
| find /var/log -name "*.log" -mtime +30 -delete
|
2. 配置logrotate
系统自动轮转日志:
1 2
| cat /etc/logrotate.d/nginx
|
3. 配合监控告警
1 2 3 4
| tail -f /var/log/app.log | grep --line-buffered "ERROR" | awk 'END{print NR}' | while read count; do [ "$count" -gt 100 ] && echo "告警:错误过多!" done
|
总结
- tail -f - 实时查看,等待问题出现时用
- journalctl - systemd的现代化日志,支持查询过滤
- grep - 搜索关键词,快速定位
- 常用组合:
journalctl -u 服务名 | grep error
- 时间过滤:
--since 和 --until 帮你找到发生问题的时刻
- 高级工具:
multitail、lnav 提升效率
- 日志要及时清理,避免占满磁盘
- 配合监控,出问题自动告警
下一篇:Docker部署个人博客实战。