日志和监控:Linux 的体检医生
引言
日志和监控是 Linux 系统管理的眼睛和耳朵。通过日志,我们可以了解系统发生了什么;通过监控,我们可以知道系统正在做什么。在这篇文章中,我们将系统学习 Linux 的日志管理和系统监控。
系统日志概述
日志的重要性
flowchart TD
A[系统事件] --> B[记录日志]
B --> C[故障排查]
B --> D[性能分析]
B --> E[安全审计]
B --> F[合规要求]
style B fill:#fff3e0
style C fill:#ffebee
style D fill:#e8f5e9
style E fill:#fff3e0
style F fill:#e3f2fd
日志位置
# 传统 syslog 日志位置
/var/log/syslog # 系统日志(Debian/Ubuntu)
/var/log/messages # 系统日志(RHEL/CentOS)
/var/log/auth.log # 认证日志
/var/log/kern.log # 内核日志
/var/log/boot.log # 启动日志
/var/log/dmesg # 启动时的内核消息
# 应用日志
/var/log/nginx/ # Nginx 日志
/var/log/apache2/ # Apache 日志
/var/log/mysql/ # MySQL 日志
日志级别
# 严重程度从高到低:
0 - emerg # 紧急,系统不可用
1 - alert # 必须立即采取措施
2 - crit # 严重情况
3 - err # 错误
4 - warning # 警告
5 - notice # 正常但重要
6 - info # 信息性消息
7 - debug # 调试信息
journald
journald 简介
journald 是 systemd 提供的日志服务,替代了传统的 syslog:
flowchart LR
A[应用] -->|日志| B[journald]
B -->|存储| C[二进制日志]
B -->|转发| D[rsyslog]
D -->|存储| E[文本日志]
style B fill:#fff3e0
style C fill:#e3f2fd
style E fill:#c8e6c9
journalctl 命令
# 查看所有日志
sudo journalctl
# 查看最新日志
sudo journalctl -e
# 实时跟踪日志
sudo journalctl -f
# 查看内核日志
sudo journalctl -k
# 查看特定单元的日志
sudo journalctl -u nginx
sudo journalctl -u sshd
# 查看最近1小时的日志
sudo journalctl --since "1 hour ago"
# 查看特定时间段的日志
sudo journalctl --since "2026-01-10 00:00:00" --until "2026-01-11 00:00:00"
# 按优先级过滤
sudo journalctl -p err # 错误级别
sudo journalctl -p notice # 通知及以上级别
# 显示详细的可读格式
sudo journalctl -o verbose
sudo journalctl -o json # JSON 格式
# 限制输出行数
sudo journalctl -n 50 # 最近50行
sudo journalctl --since today | tail -n 100
持久化日志
# 检查日志存储方式
sudo journalctl --header | grep Storage
# Storage: auto(默认,有 /var/log/journal 则持久化)
# 创建持久化存储
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
# 设置日志大小限制
sudo nano /etc/systemd/journald.conf
# SystemMaxUse=500M
# RuntimeMaxUse=100M
rsyslog
rsyslog 简介
rsyslog 是传统的 syslog 守护进程,功能强大:
# 检查 rsyslog 状态
sudo systemctl status rsyslog
# 配置文件
/etc/rsyslog.conf # 主配置文件
/etc/rsyslog.d/*.conf # 额外配置
配置示例
# /etc/rsyslog.d/myapp.conf
# 记录特定应用的日志
if $programname == 'myapp' then /var/log/myapp.log
& stop
# 记录到远程服务器
*.* @@192.168.1.100:514
# 根据严重程度记录
*.err /var/log/errors.log
*.warn /var/log/warnings.log
日志轮转(logrotate)
# 配置文件
/etc/logrotate.conf # 全局配置
/etc/logrotate.d/* # 应用配置
# 查看特定配置
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
}
# 手动执行
sudo logrotate -f /etc/logrotate.conf
# 调试模式
sudo logrotate -d /etc/logrotate.conf
系统监控工具
top/htop
# top
top
# 按 P:按 CPU 排序
# 按 M:按内存排序
# 按 T:按时间排序
# 按 k:杀死进程
# 按 r:renice
# htop(更友好)
htop
# F1-F10:功能键
# /:搜索进程
# F9:调整优先级
# F6:排序方式
vmstat
# 虚拟内存统计
vmstat 2 5 # 每2秒输出一次,共5次
# 输出解释:
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 1 0 0 123456 12345 234567 0 0 2 3 10 20 5 2 92 1 0
# r: 等待运行的进程数
# b: 不可中断睡眠的进程数
# swpd: 使用的交换空间
# free: 空闲内存
# buff: 缓冲区
# cache: 缓存
# si/so: 换入/换出
# bi/bo: 块输入/输出
# cs: 上下文切换
# us/sy/id/wa: 用户/系统/空闲/等待 CPU 时间
iostat
# 安装
sudo apt install sysstat
# I/O 统计
iostat -x 2 3
# 输出解释:
# avg-cpu: %user %nice %system %iowait %steal %idle
# 5.23 0.00 2.15 1.05 0.00 91.57
# Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
# sda 0.10 5.20 10.50 20.30 0.50 1.20 80.00 0.50 15.20 10.50 16.30 2.50 7.75
# rrqm/s: 每秒合并的读请求数
# wrqm/s: 每秒合并的写请求数
# r/s: 每秒读请求数
# w/s: 每秒写请求数
# await: 平均 I/O 等待时间
# %util: 设备利用率
pidstat
# 进程统计
pidstat 2 5 # 每2秒输出一次,共5次
# CPU 使用
pidstat -u -p 1234 1
# 内存使用
pidstat -r -p 1234 1
# 上下文切换
pidstat -w -p 1234 1
# 线程统计
pidstat -t -p 1234 1
ss/netstat
# 网络统计
ss -s # 套接字摘要
ss -tunlp # 所有监听端口
ss -tunlp | grep :80 # 查找特定端口
# netstat(旧工具)
netstat -tunlp # 所有监听端口
netstat -an # 所有连接
netstat -s # 统计信息
性能分析
CPU 性能
# 检查 CPU 数量
nproc
lscpu
# 查看 CPU 使用率
top -bn1 | grep "Cpu(s)"
mpstat -P ALL 1
# 找出 CPU 消耗高的进程
ps aux --sort=-%cpu | head -10
# 查看每个 CPU 的负载
mpstat -P ALL 1 5
# 检查 CPU 亲和性
taskset -c -p 1234
内存性能
# 查看内存使用
free -h
cat /proc/meminfo
# 查看进程内存使用
ps aux --sort=-%mem | head -10
smem -s memory # 更准确的内存统计
# 检查内存泄漏
valgrind --leak-check=full ./myapp
# 交换空间使用
swapon -s
vmstat 1 5 | grep si
磁盘 I/O
# 查看磁盘使用
df -h
du -sh * | sort -hr | head -10
# 磁盘 I/O 性能
iostat -x 1 5
# 查找 I/O 密集的进程
iotop
pidstat -d 1
# 磁盘速度测试
dd if=/dev/zero of=testfile bs=1G count=1 oflag=direct
网络性能
# 网络带宽
iftop # 实时带宽使用
nethogs # 按进程显示
speedtest-cli # 网速测试
# 网络连接统计
ss -s
netstat -an | wc -l
# 抓包分析
tcpdump -i eth0 -w capture.pcap
wireshark capture.pcap
实战脚本
系统健康检查
#!/bin/bash
# health_check.sh
echo "=== System Health Check ==="
echo "Time: $(date)"
echo ""
# CPU 使用率
echo "--- CPU Usage ---"
CPU_IDLE=$(top -bn1 | grep "Cpu(s)" | awk '{print $8}' | cut -d'%' -f1)
CPU_USED=$(echo "100 - $CPU_IDLE" | bc)
echo "CPU Used: ${CPU_USED}%"
if (( $(echo "$CPU_USED > 80" | bc -l) )); then
echo "⚠️ WARNING: High CPU usage!"
fi
# 内存使用
echo ""
echo "--- Memory Usage ---"
MEM_INFO=$(free -m | awk 'NR==2{printf "%.2f", $3*100/$2}')
echo "Memory Used: ${MEM_INFO}%"
if (( $(echo "$MEM_INFO > 80" | bc -l) )); then
echo "⚠️ WARNING: High memory usage!"
fi
# 磁盘使用
echo ""
echo "--- Disk Usage ---"
df -h | grep -E '^/dev/' | while read line; do
USAGE=$(echo $line | awk '{print $5}' | cut -d'%' -f1)
MOUNT=$(echo $line | awk '{print $6}')
echo "$MOUNT: ${USAGE}%"
if [ $USAGE -gt 80 ]; then
echo "⚠️ WARNING: $MOUNT is ${USAGE}% full!"
fi
done
# 系统负载
echo ""
echo "--- System Load ---"
UPTIME=$(uptime | awk -F'load average:' '{print $2}')
echo "Load Average:$UPTIME"
# 错误日志
echo ""
echo "--- Recent Errors ---"
journalctl -p err -n 5 --no-pager
性能监控脚本
#!/bin/bash
# performance_monitor.sh
OUTPUT_FILE="performance_$(date +%Y%m%d_%H%M%S).log"
echo "Timestamp,CPU%,Memory%,Disk%,Network_RX,Network_TX" > $OUTPUT_FILE
while true; do
# CPU
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
# Memory
MEM=$(free | awk 'NR==2{printf "%.2f", $3*100/$2}')
# Disk (根分区)
DISK=$(df / | awk 'NR==2{print $5}' | cut -d'%' -f1)
# Network
NET_RX=$(cat /sys/class/net/eth0/statistics/rx_bytes)
NET_TX=$(cat /sys/class/net/eth0/statistics/tx_bytes)
echo "$(date +%s),$CPU,$MEM,$DISK,$NET_RX,$NET_TX" >> $OUTPUT_FILE
sleep 1
done
总结
日志和监控是系统管理的关键技能。通过这篇文章,我们学习了:
核心工具
- journald:systemd 日志服务
- rsyslog:传统日志守护进程
- logrotate:日志轮转
- top/htop:进程监控
- vmstat/iostat:性能统计
实践技能
- 使用
journalctl查询系统日志 - 配置日志轮转策略
- 分析 CPU、内存、磁盘、网络性能
- 编写监控脚本
最佳实践
- 定期检查日志:建立日志审查习惯
- 设置告警:异常情况及时通知
- 保留历史数据:便于趋势分析
- 自动化监控:减少人工干预
“You can’t improve what you don’t measure.” — Peter Drucker
监控和日志管理是系统稳定运行的保障。掌握这些工具,让你的 Linux 系统管理更上一层楼!
← 返回系列概述: Linux 概述:从 Unix 到开源革命
参考资源: