📋 第11课:日志系统

阶段二:用户与进程第5/6课

📚 课程目标

一、Linux日志体系

应用程序 ──┬── systemd-journald ──→ /run/log/journal/ (二进制)
            └── rsyslog ──────────→ /var/log/ (文本文件)

1.1 日志优先级

代码关键字说明
0emerg系统不可用
1alert必须立即处理
2crit严重情况
3err错误情况
4warning警告情况
5notice正常但值得注意
6info信息性消息
7debug调试消息

1.2 日志设施(Facility)

设施代码来源
kern0内核消息
user1用户进程
mail2邮件系统
daemon3系统守护进程
auth4认证系统
local0-716-23本地自定义

二、/var/log目录

$ ls /var/log/ | head -20
alternatives.log
alternatives.log.1
apport.log
apport.log.1
apport.log.2.gz
apt
auth.log
auth.log.1
auth.log.2.gz
boot.log
boot.log.1
boot.log.2
boot.log.3
bootstrap.log
btmp
btmp.1
chrony
cloud-init.log
cloud-init-output.log
containers

📋 常见日志文件

文件内容
/var/log/syslog系统总日志(Debian/Ubuntu)
/var/log/messages系统总日志(RHEL/CentOS)
/var/log/auth.log认证日志(Debian)
/var/log/secure认证日志(RHEL)
/var/log/kern.log内核日志
/var/log/wtmp登录记录(binary, last查看)
/var/log/btmp失败登录(binary, lastb查看)
/var/log/lastlog用户最后登录(lastlog查看)

三、journalctl高级用法

$ journalctl --disk-usage
Archived and active journals take up 77.6M in the file system.
# 按服务查询
journalctl -u nginx.service
journalctl -u nginx --since today

# 按时间查询
journalctl --since "1 hour ago"
journalctl --since yesterday
journalctl --since "09:00" --until "10:00"

# 按优先级查询
journalctl -p err               # 错误及以上
journalctl -p warning

# 按进程/用户查询
journalctl _PID=1234
journalctl _UID=1000

# 输出格式
journalctl -o json-pretty
journalctl -o cat               # 仅消息内容

# 实时跟踪
journalctl -f                   # 类似tail -f

# 内核日志
journalctl -k

四、rsyslog配置

$ cat /etc/rsyslog.conf 2>/dev/null | grep -v '^#' | grep -v '^$' | head -15
module(load="imuxsock") # provides support for local system logging
module(load="imklog" permitnonkernelfacility="on")
$RepeatedMsgReduction on
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog
$WorkDirectory /var/spool/rsyslog
$IncludeConfig /etc/rsyslog.d/*.conf

4.1 rsyslog规则语法

# 格式:设施.优先级  动作
*.info;mail.none;authpriv.none;cron.none  /var/log/messages
authpriv.*                                /var/log/secure
*.emerg                                   :omusrmsg:*
local7.*                                  /var/log/boot.log

4.2 远程日志转发

# 服务端配置(接收日志)
module(load="imudp")
input(type="imudp" port="514")
module(load="imtcp")
input(type="imtcp" port="514")

# 客户端配置(发送日志)
*.* @@log-server:514     # TCP转发
*.* @log-server:514      # UDP转发

五、logrotate日志轮转

$ cat /etc/logrotate.conf | head -20
# see "man logrotate" for details

# global options do not affect preceding include directives

# rotate log files weekly
weekly

# use the adm group by default, since this is the owning group
# of /var/log/.
su root adm

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
#dateext
# /etc/logrotate.d/nginx 示例
/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0644 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}

# 手动测试轮转
sudo logrotate -d /etc/logrotate.d/nginx   # 调试模式
sudo logrotate -f /etc/logrotate.d/nginx   # 强制轮转

六、日志分析实战

# 分析SSH暴力破解
journalctl -u sshd | grep "Failed password" | \
  awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

# 查找sudo使用记录
journalctl -t sudo

# 查找OOM Killer
dmesg | grep -i "oom"
journalctl -k | grep -i "out of memory"

# 分析系统崩溃
journalctl -b -1 -p err
$ dmesg | tail -10
[ 3804.965085] docker0: port 1(veth6839367) entered forwarding state
[ 3805.087047] docker0: port 1(veth6839367) entered disabled state
[ 3805.087953] veth4b88a38: renamed from eth0
[ 3805.123983] docker0: port 1(veth6839367) entered disabled state
[ 3805.124730] veth6839367 (unregistering): left allmulticast mode
[ 3805.124735] veth6839367 (unregistering): left promiscuous mode
[ 3805.124738] docker0: port 1(veth6839367) entered disabled state
[ 3857.713209] hrtimer: interrupt took 1512261 ns
[ 6592.900445] workqueue: vmstat_shepherd hogged CPU for >10000us 8 times, consider switching to WQ_UNBOUND
[22948.875058] workqueue: vmstat_shepherd hogged CPU for >10000us 16 times, consider switching to WQ_UNBOUND

七、ELK日志平台简介

企业级日志管理通常使用ELK (Elasticsearch + Logstash + Kibana) 或 EFK (Fluentd替代Logstash) 技术栈。

应用服务器 ──→ Filebeat ──→ Logstash ──→ Elasticsearch ──→ Kibana
                  采集        过滤处理      存储索引         可视化

📋 ELK vs rsyslog

特性rsyslogELK
规模单机/小集群大规模分布式
搜索grep全文搜索
可视化Kibana仪表板
告警脚本ElastAlert/Watcher
成本高(资源消耗大)

八、故障排查

❌ 问题:日志文件过大

du -sh /var/log/*
journalctl --disk-usage

# 清理journal
sudo journalctl --vacuum-time=7d
sudo journalctl --vacuum-size=500M

# 配置journal大小限制 /etc/systemd/journald.conf
# SystemMaxUse=500M

❌ 问题:日志丢失

# 检查journal是否持久化
ls /var/log/journal/   # 持久化存储
ls /run/log/journal/   # 内存存储(重启丢失)

# 启用持久化
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald

九、练习

📝 日志分析实战

# 1. 查看本次启动的所有错误
journalctl -b -p err

# 2. 查看SSH登录失败记录
journalctl -u sshd | grep "Failed" | tail -10

# 3. 查看系统最近重启记录
last reboot | head -5

# 4. 查看登录失败记录
sudo lastb | head -10

# 5. 查看磁盘IO错误
dmesg | grep -i "error\|i/o"
🏆

成就解锁:日志分析师

✅ 理解Linux日志体系

✅ 掌握journalctl高级查询

✅ 了解rsyslog配置与转发

✅ 学会logrotate日志轮转

✅ 掌握日志分析实战技巧

十、日志安全与合规

10.1 日志安全最佳实践

# 使用auditd审计关键文件访问
sudo apt install auditd
sudo auditctl -w /etc/passwd -p wa -k passwd_changes
sudo auditctl -w /etc/sudoers -p wa -k sudoers_changes
sudo auditctl -a exit,always -F arch=b64 -S unlink -S unlinkat -k file_delete

# 查看审计日志
sudo ausearch -k passwd_changes
sudo aureport -f    # 文件访问报告

10.2 日志合规要求

📋 等保2.0日志要求

十一、自定义日志处理脚本

#!/bin/bash
# log-analyzer.sh - 日志分析脚本
LOG_DIR="/var/log"
REPORT="/tmp/log-report-$(date +%Y%m%d).txt"

echo "===== 日志分析报告 =====" > "$REPORT"
echo "日期: $(date)" >> "$REPORT"
echo >> "$REPORT"

# 系统错误统计
echo "--- 系统错误统计 ---" >> "$REPORT"
journalctl -p err --since "24 hours ago" |   awk '{print $5}' | sort | uniq -c | sort -rn | head -10 >> "$REPORT"
echo >> "$REPORT"

# SSH暴力破解检测
echo "--- SSH暴力破解IP ---" >> "$REPORT"
journalctl -u sshd --since "24 hours ago" |   grep "Failed password" |   awk '{for(i=1;i<=NF;i++) if($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $i}' |   sort | uniq -c | sort -rn | head -10 >> "$REPORT"
echo >> "$REPORT"

# 磁盘空间警告
echo "--- 磁盘空间使用 ---" >> "$REPORT"
df -h | awk 'NR>1 && int($5)>80 {print}' >> "$REPORT"

echo "Report saved to $REPORT"
cat "$REPORT"

十二、日志监控告警

#!/bin/bash
# log-alert.sh - 关键日志实时告警
# 配合cron每5分钟运行

KEYWORDS="error|critical|failed|denied|attack"
LOG_CMD="journalctl --since '5 minutes ago'"
ALERT_EMAIL="admin@example.com"

# 检查关键错误
errors=$($LOG_CMD | grep -iE "$KEYWORDS" | grep -v "CRON")
if [ -n "$errors" ]; then
    echo "$errors" | mail -s "[ALERT] System errors detected on $(hostname)" "$ALERT_EMAIL" 2>/dev/null
    # 或发送到webhook
    # curl -X POST "https://hooks.slack.com/xxx" -d '{"text":"'"$errors"'"}'
fi
生产环境推荐使用专业监控工具(Prometheus + Alertmanager、Zabbix、Nagios)而非自写脚本。但对于小规模部署,cron+脚本方案足够且简单。