应用程序 ──┬── systemd-journald ──→ /run/log/journal/ (二进制)
└── rsyslog ──────────→ /var/log/ (文本文件)
| 代码 | 关键字 | 说明 |
|---|---|---|
| 0 | emerg | 系统不可用 |
| 1 | alert | 必须立即处理 |
| 2 | crit | 严重情况 |
| 3 | err | 错误情况 |
| 4 | warning | 警告情况 |
| 5 | notice | 正常但值得注意 |
| 6 | info | 信息性消息 |
| 7 | debug | 调试消息 |
| 设施 | 代码 | 来源 |
|---|---|---|
| kern | 0 | 内核消息 |
| user | 1 | 用户进程 |
| 2 | 邮件系统 | |
| daemon | 3 | 系统守护进程 |
| auth | 4 | 认证系统 |
| local0-7 | 16-23 | 本地自定义 |
$ 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 --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
$ 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
# 格式:设施.优先级 动作
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
*.emerg :omusrmsg:*
local7.* /var/log/boot.log
# 服务端配置(接收日志)
module(load="imudp")
input(type="imudp" port="514")
module(load="imtcp")
input(type="imtcp" port="514")
# 客户端配置(发送日志)
*.* @@log-server:514 # TCP转发
*.* @log-server:514 # UDP转发
$ 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 (Elasticsearch + Logstash + Kibana) 或 EFK (Fluentd替代Logstash) 技术栈。
应用服务器 ──→ Filebeat ──→ Logstash ──→ Elasticsearch ──→ Kibana
采集 过滤处理 存储索引 可视化
| 特性 | rsyslog | ELK |
|---|---|---|
| 规模 | 单机/小集群 | 大规模分布式 |
| 搜索 | 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日志轮转
✅ 掌握日志分析实战技巧
# 使用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 # 文件访问报告
#!/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