日志是服务器的”黑匣子”——每一次攻击尝试、每一次服务崩溃、每一次 OOM 内存爆炸,都在日志里留下了痕迹。本指南将带您从零掌握 Linux 日志体系,学会用 awk/grep 提取关键信息,并通过真实案例演示五大高频故障的完整排查流程。
🗂️ Linux 日志体系全貌
Linux 有两套并行的日志系统,理解它们的关系是高效排错的基础: 📔
systemd Journal
journalctl 命令访问
现代 Linux(systemd 管理的服务)的统一日志中心。以二进制格式存储在 /var/log/journal/,支持结构化查询、按优先级过滤、跨重启查询。Ubuntu 16.04+、Debian 9+ 均默认使用。
📁
传统 syslog 文件
/var/log/ 目录文本文件
由 rsyslog/syslog-ng 写入的纯文本日志文件。可直接用 cat、grep、awk 处理,无需特殊工具,也是 Nginx、MySQL 等应用程序的默认输出目标。
💡 两套系统的关系: 默认配置下,systemd 日志既写入 Journal(journalctl 可查),也通过 rsyslog 转发到 /var/log/syslog。排查时两个都要看:systemd 服务用 journalctl -u 服务名,攻击分析和流量统计用 grep/awk 处理文本文件。
日志文件速查手册
日志文件路径 适用发行版 记录内容 /var/log/syslog Debian/Ubuntu 系统主日志,内核消息、服务启停、cron 执行记录 /var/log/messages CentOS/RHEL 等同于 syslog,系统综合日志 /var/log/auth.log Debian/Ubuntu 所有认证事件:SSH 登录、sudo、PAM(排查入侵首选) /var/log/secure CentOS/RHEL 等同于 auth.log /var/log/kern.log 通用 内核消息:硬件错误、驱动崩溃、OOM killer 触发记录 /var/log/dmesg 通用 系统启动时的内核环形缓冲区,用 dmesg 命令读取 /var/log/boot.log 通用 系统启动过程中各服务的启动状态 /var/log/dpkg.log Debian/Ubuntu apt/dpkg 软件包安装、升级、删除的完整记录 /var/log/nginx/access.log Nginx 每一条 HTTP 请求记录:IP、时间、路径、状态码、耗时 /var/log/nginx/error.log Nginx Nginx 错误与警告:502、403、配置问题等 /var/log/mysql/error.log MySQL MySQL 启动错误、崩溃恢复、连接拒绝等 /var/log/fail2ban.log Fail2ban Fail2ban 触发封禁的 IP 和 jail 名称记录
📔 journalctl:systemd 统一日志中心
journalctl 是查询 systemd Journal 的核心命令。排查服务问题时,它应该是您打开的第一个工具——特别是 journalctl -b -1 -p err,这是排查意外重启后的首选命令。
journalctl 完整速查
# ── 基础查看 ────────────────────────────────────────────────────────────────
journalctl # 全部日志(从最旧开始,按 q 退出)
journalctl -r # 倒序显示(最新在最前,排查时最常用)
journalctl -f # 实时追踪(类似 tail -f,Ctrl+C 退出)
journalctl -n 100 # 仅显示最近 100 行
journalctl --no-pager # 不分页,直接输出(方便管道处理)
# ── 按服务过滤 ──────────────────────────────────────────────────────────────
journalctl -u nginx # 只看 nginx 服务的日志
journalctl -u nginx -u mysql # 同时查看 nginx 和 mysql
journalctl -u nginx -f # 实时追踪 nginx 日志
journalctl -u nginx --since today # 今天的 nginx 日志
# ── 按时间过滤 ──────────────────────────────────────────────────────────────
journalctl --since "2026-03-16 08:00:00"
journalctl --since "2026-03-16 08:00" --until "2026-03-16 10:00"
journalctl --since "1 hour ago"
journalctl --since yesterday
# ── 按优先级过滤(0=emerg 1=alert 2=crit 3=err 4=warn 5=notice 6=info 7=debug)
journalctl -p err # 只看错误及以上级别
journalctl -p warning -u nginx # nginx 的警告及以上
journalctl -p 0..3 # emerg 到 err 级别
# ── 查看上次启动日志(排查死机/重启原因)──────────────────────────────────
journalctl -b # 本次启动的所有日志
journalctl -b -1 # 上一次启动的日志
journalctl -b -1 -p err # 上次启动中的错误日志(排查崩溃首选)
journalctl --list-boots # 列出所有可查询的启动记录
# ── 磁盘占用管理 ────────────────────────────────────────────────────────────
journalctl --disk-usage # 查看 journal 占用的磁盘空间
journalctl --vacuum-time=30d # 删除 30 天前的日志
journalctl --vacuum-size=500M # 将日志总量控制在 500MB 以内
`journalctl -b -1 -p err` 排查上次崩溃 意外重启后第一个要跑的命令 `journalctl -u nginx -f` 实时追踪服务 服务异常时实时观察日志流 `journalctl --vacuum-time=30d` 清理旧日志 释放被 journal 占用的磁盘
📁 传统日志文件速查手册
/var/log/ 下的传统文本日志在安全分析和攻击溯源方面依然不可替代——grep/awk 直接处理文本,速度极快且无需学习特殊工具。
auth.log:排查 SSH 暴力破解与入侵
/var/log/auth.log 分析命令
# ── auth.log:排查 SSH 暴力破解与入侵 ────────────────────────────────────────
# 查看最近的 SSH 认证失败记录
grep "Failed password" /var/log/auth.log | tail -50
# 统计攻击来源 IP(按攻击次数降序排列)
grep "Failed password" /var/log/auth.log \
| awk '{print $(NF-3)}' \
| sort | uniq -c | sort -rn \
| head -20
# 输出示例:
# 3842 185.220.101.47
#### 🚨 真实攻击溯源示例
# 统计攻击来源 IP,发现异常:
3842 185.220.101.47 ← Tor 出口节点,字典攻击 3842 次
127 45.33.32.156 ← Shodan 扫描器
# 查看成功登录记录(关键:确认无未授权登录)
Accepted publickey for ubuntu from 192.168.1.100 port 52341
# ✅ 只有自己的 IP 成功登录,3842 次攻击全部失败
### kern.log / dmesg:排查 OOM 与硬件错误
/var/log/kern.log + dmesg
── kern.log:排查 OOM(内存不足杀进程)──────────────────────────────────────
搜索 OOM killer 触发记录
grep -i “oom|out of memory|kill process” /var/log/kern.log | tail -30
或用 journalctl:
journalctl -k | grep -i “oom|out of memory” | tail -30
OOM 日志示例:
Mar 16 03:42:17 vps01 kernel: Out of memory: Kill process 12847 (php-fpm) score 892
Mar 16 03:42:17 vps01 kernel: Killed process 12847 (php-fpm) total-vm:524288kB, anon-rss:418764kB
查看当前内存使用详情
free -h
查看各进程内存占用排行
ps aux —sort=-%mem | head -15
── dmesg:排查硬件错误 ──────────────────────────────────────────────────────
dmesg -T # 显示带时间戳的内核消息 dmesg -T | grep -i “error|fail|warn” | tail -30 dmesg -T | grep -i “disk|sda|nvme” # 排查磁盘 I/O 错误 dmesg -T | grep -i “oom|memory” # 内存相关内核消息
── 查看系统崩溃/重启原因 ──────────────────────────────────────────────────
last reboot | head -10 # 最近的重启记录 last -x | grep shutdown | head -5 # 最近的关机记录
## 🔬 实战:awk/grep/sed/cut 日志分析四件套
这四个工具是 Linux 日志分析的核心利器,无需安装依赖,掌握它们能解决 90% 的日志分析需求:
🔍 `grep` 关键词过滤
从大量日志中快速找到包含特定关键词的行,支持正则表达式。
`grep "ERROR" /var/log/nginx/error.log` 找所有 ERROR 行 `grep -v "GET /favicon" access.log` -v 反向过滤(排除某类日志) `grep -c "Failed" auth.log` -c 只统计匹配行数 `grep -r "exception" /var/log/app/` -r 递归搜索目录 `grep -E "404|500|502" access.log` -E 扩展正则,多关键词 ✂️ `awk` 字段提取与统计
按列提取字段,进行统计计数。Nginx 日志分析的核心工具。
`awk '{print $1}' access.log` 打印第 1 列(IP 地址) `awk '{print $9}' access.log | sort | uniq -c` 统计状态码分布 `awk '$9==502' access.log` 过滤状态码为 502 的行 `awk '{sum+=$10} END{print sum}' access.log` 累加第 10 列(流量统计) `awk 'NR>=100 && NR<=200' access.log` 只打印第 100-200 行 ✏️ `sed` 文本替换与提取
流式文本编辑,常用于日志格式转换和敏感信息脱敏。
`sed -n '100,200p' access.log` -n + p:打印指定行范围 `sed 's/password=[^ ]*/password=***/' auth.log` 脱敏密码字段 `sed '/healthcheck/d' access.log` 删除含关键词的行 `sed -n '/03:00/,/04:00/p' syslog` 提取时间范围内的日志 `sed 's/\[.*\]//' error.log` 删除方括号内的时间戳 🗡️ `cut` 按分隔符切列
按指定分隔符快速提取某一列,比 awk 简单直接。
`cut -d' ' -f1 access.log` -d 指定分隔符,-f 指定列号 `cut -d'"' -f2 access.log` 提取引号内的请求行 `cut -d':' -f1 /etc/passwd` 提取系统用户名列表 `cut -c1-15 syslog` -c 按字符位置,提取时间戳 `cut -d' ' -f1,4,9 access.log` 同时提取第 1、4、9 列
## 🌐 实战:Nginx 日志深度分析
Nginx 访问日志是运维工作中频率最高的日志分析对象——网站变慢了、被攻击了、出现 502 了,第一个要看的都是它。
### 理解 Nginx 日志格式
log_format 字段说明
Nginx 默认日志格式字段说明(/etc/nginx/nginx.conf 中 log_format)
字段顺序:IP - 用户 [时间] “方法 路径 协议” 状态码 字节数 “Referer” “UA”
示例行:
185.220.101.47 - - [16/Mar/2026:03:42:17 +0000] “GET /wp-login.php HTTP/1.1” 404 162 ”-” “Mozilla/5.0”
103.21.244.12 - - [16/Mar/2026:03:42:19 +0000] “POST /xmlrpc.php HTTP/1.1” 403 144 ”-” “python-requests/2.28”
── 推荐开启 JSON 格式日志(更易于程序化分析)────────────────────────────────
在 nginx.conf http{} 块中添加(注意 Astro 不解析此处,直接使用即可):
log_format json_combined escape=json
’{'
'“time”:“$time_iso8601”,'
'“remote_addr”:“$remote_addr”,'
'“method”:“$request_method”,'
'“uri”:“$request_uri”,'
'“status”:$status,'
'“request_time”:$request_time,'
'“upstream_time”:“$upstream_response_time”'
'}‘;
access_log /var/log/nginx/access.log json_combined;
### access.log 常用分析命令
/var/log/nginx/access.log 分析
── Nginx access.log 常用分析命令 ──────────────────────────────────────────
1. 统计访问量最高的 10 个 IP
awk ‘{print $1}’ /var/log/nginx/access.log
| sort | uniq -c | sort -rn | head -10
2. 统计访问最多的 URL(排除静态资源)
awk ‘{print $7}’ /var/log/nginx/access.log
| grep -vE ’.(css|js|png|jpg|ico|woff)$’
| sort | uniq -c | sort -rn | head -20
3. 统计各 HTTP 状态码数量(判断服务整体健康)
awk ‘{print $9}’ /var/log/nginx/access.log
| sort | uniq -c | sort -rn
若 502 大量出现 -> PHP-FPM/后端服务崩溃
若 499 大量出现 -> 客户端主动断开(CC 攻击特征)
4. 找出响应时间最慢的请求(需日志含 request_time 字段)
awk ‘{print $NF, $7}’ /var/log/nginx/access.log
| sort -rn | head -20
5. 统计某个 IP 今天的请求次数
grep “^1.2.3.4 ” /var/log/nginx/access.log | wc -l
6. 实时监控 502 错误
tail -f /var/log/nginx/access.log | grep —line-buffered ” 502 “
7. 分析某个被封 IP 都访问了哪些路径
BANNED_IP=“185.220.101.47”
grep ”^${BANNED_IP} ” /var/log/nginx/access.log
| awk ‘{print $7}’ | sort | uniq -c | sort -rn | head -20
状态码 含义 大量出现时的排查方向 200 成功 正常,无需关注 403 禁止访问 大量 403 到敏感路径 = 漏洞扫描,考虑 Fail2ban 封锁 404 未找到 大量 404 到 wp-login.php 等 = 漏洞扫描 499 客户端主动断开 大量 499 = CC 攻击特征,客户端发完请求立即断开 502 网关错误 后端服务(PHP-FPM/应用)崩溃,查后端日志 503 服务不可用 后端过载或全部失效,检查后端状态 504 网关超时 后端响应太慢,检查慢查询或应用代码性能
## 🐢 实战:MySQL 慢查询日志
数据库查询慢是导致网站响应迟缓的最常见原因之一,慢查询日志记录了每一条执行超过阈值时间的 SQL,以及扫描了多少行——通过它能精准定位缺少索引的问题查询。
MySQL 慢查询日志配置与分析
── 开启 MySQL 慢查询日志(在线热开启,无需重启)────────────────────────────
登录 MySQL 后执行:
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; — 超过 1 秒记录
SET GLOBAL slow_query_log_file = ‘/var/log/mysql/slow.log’;
SET GLOBAL log_queries_not_using_indexes = ON; — 记录未用索引的查询
或在 /etc/mysql/mysql.conf.d/mysqld.cnf 中持久化:
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
── 分析慢查询日志 ──────────────────────────────────────────────────────────
使用 mysqldumpslow(MySQL 官方自带工具)
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
-s t 按总执行时间排序
-t 10 只显示 Top 10
慢查询日志示例:
Time: 2026-03-16T03:42:17.123456Z
Query_time: 4.523891 Lock_time: 0.000102 Rows_sent: 1 Rows_examined: 2847361
SELECT * FROM orders WHERE user_id = 12345;
扫描 284 万行只返回 1 行 -> 缺少 user_id 索引!
用 pt-query-digest(分析更详细)
apt install percona-toolkit -y pt-query-digest /var/log/mysql/slow.log | head -100
## 🚨 五大高频故障排查全流程
以下是 VPS 运维中最常遇到的五类故障,每个都附有完整的排查命令序列——按顺序执行即可系统性定位问题根因:
💥
#### 故障①:服务器突然重启 / OOM 内存爆炸
现象:VPS 突然断线,重连后 uptime 只有几分钟,不知道发生了什么
排查命令序列
故障场景①:服务器突然重启,不知道原因
步骤1:确认是否意外重启
last reboot | head -5
步骤2:查看上次启动前的最后日志
journalctl -b -1 -p err —no-pager | tail -50
关注:
“Out of memory: Kill process” -> OOM,内存耗尽
”Kernel panic” -> 内核崩溃
”EXT4-fs error” -> 磁盘文件系统损坏
步骤3:若是 OOM,找出是哪个进程消耗了内存
journalctl -b -1 -k | grep -i “oom|killed process”
示例输出:
kernel: Killed process 8472 (java) total-vm:4194304kB, anon-rss:3876000kB
-> Java 进程用了约 3.8GB 物理内存后被 OOM killer 终止
步骤4:防止下次 OOM
策略A:为服务设置内存上限(在 systemd service 文件 [Service] 段中):
MemoryMax=512M
MemorySwapMax=0
策略B:增加 swap 空间
fallocate -l 2G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo ‘/swapfile none swap sw 0 0’ >> /etc/fstab
💿
#### 故障②:磁盘空间耗尽,服务写入失败
现象:数据库写入失败、Nginx 无法记录日志、Docker 无法启动新容器
排查命令序列
故障场景②:磁盘空间满了,服务写入失败
步骤1:确认磁盘使用情况
df -h
步骤2:找出占用空间最大的目录
du -sh /* 2>/dev/null | sort -rh | head -15 du -sh /var/log/* 2>/dev/null | sort -rh | head -10
步骤3:常见空间杀手与清理方法
A. 日志文件膨胀:先保留证据,再通过轮转释放空间
ls -lh /var/log/nginx/*.log logrotate -d /etc/logrotate.d/nginx # 预演,不写入 logrotate -f /etc/logrotate.d/nginx # 确认规则正确后再强制轮转
B. apt 缓存堆积
du -sh /var/cache/apt/ apt clean
apt autoremove 先不加 -y,审阅待删除包后再确认
C. Docker 垃圾
docker system df docker image prune # 交互确认,仅清理悬空镜像
不要在故障处理中直接使用 —volumes;先核对挂载、备份和恢复点
D. 旧内核(Ubuntu 常见)
dpkg —list | grep linux-image apt autoremove —purge # 审阅清单,保留当前和回退内核
E. 全局大文件查找(超过 100MB)
find / -type f -size +100M 2>/dev/null | xargs ls -lh | sort -k5 -rh | head -20
步骤4:df 有空间但 du 统计不到(已删除但被占用的文件)
lsof +L1 | head -20
先定位持有文件的具体 PID 和服务,再安排 reload/restart;
不要把 nginx、mysql 作为一条命令无差别重启
🔐
#### 故障③:SSH 无法连接,被锁在门外
现象:SSH 连接超时或被拒绝,服务器黑屏,不知道从何下手
排查命令序列
故障场景③:SSH 无法连接,排查与恢复
── 诊断阶段(从本地机器执行)───────────────────────────────────────────────
测试1:服务器是否在线
ping -c 5 服务器IP
测试2:SSH 端口是否开放
nc -zv 服务器IP 22
测试3:SSH 连接详细调试
ssh -vvv user@服务器IP -p 22
── 常见原因与解决(通过 VPS 控制台 VNC/Console 操作)───────────────────────
原因A:防火墙误封 SSH 端口
ufw allow 22/tcp && ufw reload
或:iptables -I INPUT -p tcp —dport 22 -j ACCEPT
原因B:Fail2ban 误封了您的 IP
fail2ban-client status sshd # 查看被封 IP 列表 fail2ban-client set sshd unbanip 您的IP # 解封
原因C:SSH 服务或配置异常(Debian/Ubuntu 通常为 ssh.service)
systemctl status ssh journalctl -u ssh -n 50 —no-pager sshd -t
只有配置校验通过后才按发行版服务名重载或重启
systemctl reload ssh
原因D:磁盘满导致 SSH 无法记录日志或创建运行文件
先按故障②保留证据并释放最小空间,再检查服务
── 预防措施 ────────────────────────────────────────────────────────────────
修改防火墙前保留控制台入口,并先添加新端口:
ufw status numbered ufw allow 22222/tcp
新终端验证成功后,才删除旧 SSH 端口规则;
不要把“自动关闭整个 UFW”当作回滚方案
⚠️
#### 故障④:网站出现 502 Bad Gateway
现象:访问网站显示 502,Nginx 在运行但网页打不开
排查命令序列
故障场景④:网站出现 502 Bad Gateway
步骤1:确认 Nginx 是否在运行
systemctl status nginx
步骤2:查看 Nginx error.log(502 的直接原因)
tail -50 /var/log/nginx/error.log
常见错误:
“connect() failed (111: Connection refused)” -> 后端服务没在监听
”no live upstreams while connecting” -> 所有 upstream 都挂了
”upstream timed out (110: Connection timed out)”-> 后端响应超时
步骤3:检查后端服务状态
systemctl status php8.3-fpm journalctl -u php8.3-fpm -n 30 —no-pager
步骤4:确认后端端口是否在监听
ss -tlnp | grep ‘:9000’ # PHP-FPM 默认端口 ss -tlnp | grep ‘:3000’ # Node.js 常见端口
步骤5:检查系统资源(可能是 OOM 触发了 PHP-FPM 被杀)
free -h && journalctl -k | grep -i “oom” | tail -10
🔥
#### 故障⑤:CPU 突然飙升至 100%
现象:服务器响应极慢,SSH 卡顿,top 显示 CPU 接近满载
排查命令序列
故障场景⑤:CPU 突然飙升至 100%
步骤1:快速定位占用 CPU 最多的进程
top -b -n 1 | head -20
或:
ps aux —sort=-%cpu | head -15
步骤2:查看该进程在做什么(以 PID 12345 为例)
ls -la /proc/12345/fd # 打开的文件描述符 cat /proc/12345/cmdline | tr ‘\0’ ’ ’ # 完整启动命令
步骤3:若是 Nginx worker 占满 CPU(CC 攻击特征)
tail -100 /var/log/nginx/access.log | awk ‘{print $1}’ | sort | uniq -c | sort -rn | head -5
找到攻击 IP 后立即封禁:
ufw deny from 攻击IP
步骤4:检查是否有挖矿程序(CPU 100% 且进程名可疑)
ps aux | grep -v ”[” | sort -k3 -rn | head -10
若发现陌生进程,检查其网络连接:
ss -tlnp | grep PID netstat -anp | grep PID
步骤5:检查 cron 任务是否触发高负载
crontab -l cat /etc/cron.d/*
## 📊 进阶:GoAccess 与 lnav 可视化工具
纯命令行分析功能强但不直观。GoAccess 提供流量全局概览,lnav 提供跨文件交互式排查——两者互补,覆盖不同场景:
📈
#### GoAccess
实时 Nginx/Apache **流量可视化仪表板**,支持终端 TUI 和独立 HTML 报告。能直观看到访客地图、Top URL、Top IP、状态码分布,无需搭建 ELK 等复杂系统。
🔎
#### lnav
**交互式多文件日志浏览器**,自动按时间合并多个日志、高亮错误行、支持正则搜索和 SQL 查询。排查跨服务的复杂故障极为高效。
### GoAccess 安装与使用
GoAccess
── GoAccess:Nginx 日志实时可视化仪表板 ──────────────────────────────────
安装(Ubuntu/Debian)
apt install goaccess -y
终端实时查看(TUI 模式)
goaccess /var/log/nginx/access.log —log-format=COMBINED
生成独立 HTML 报告
goaccess /var/log/nginx/access.log
—log-format=COMBINED
-o /tmp/nginx-report.html
scp 到本地查看:scp user@服务器IP:/tmp/nginx-report.html ~/Desktop/
分析历史压缩日志(支持通配符合并分析)
zcat /var/log/nginx/access.log.*.gz |
goaccess - —log-format=COMBINED -o /tmp/history-report.html
常用面板(终端模式按数字键切换):
1 - 访客统计(Unique Visitors)
2 - 请求路径(Requested Files)
4 - 404 错误(Not Found)
5 - 来源国家(GeoLocation)
8 - 时间分布(Visit Time)
### lnav 安装与使用
lnav
── lnav:交互式多文件日志浏览器 ──────────────────────────────────────────
安装
apt install lnav -y
同时查看多个日志文件(按时间交错合并显示)
lnav /var/log/auth.log /var/log/syslog /var/log/nginx/error.log
打开 systemd journal
lnav /var/log/journal/
── lnav 内部快捷键 ──────────────────────────────────────────────────────────
/pattern 正则搜索
n / N 下一个/上一个匹配
e / E 跳到下一个/上一个错误行(自动识别 ERROR/WARN)
q 退出
TAB 切换文件面板
: 打开命令模式(可执行 SQL 查询!)
lnav SQL 查询示例(: 提示符后输入):
SELECT cs_ip, count(*) as cnt FROM access_log GROUP BY cs_ip ORDER BY cnt DESC LIMIT 10;
SELECT * FROM syslog WHERE log_level = ‘error’ ORDER BY log_time DESC LIMIT 50;
## 🏗️ 进阶:rsyslog 集中式日志汇聚
当您管理多台 VPS 时,逐台 SSH 查日志效率极低。通过 rsyslog 将所有服务器的日志汇聚到一台"日志中心",可以在一处搜索全部机器的历史记录。
/etc/rsyslog.conf(日志汇聚服务端)
── rsyslog 服务端配置(日志汇聚中心)────────────────────────────────────
编辑 /etc/rsyslog.conf,开启 TCP 监听(比 UDP 更可靠):
module(load=“imtcp”)
input(type=“imtcp” port=“514”)
按来源主机分目录存储日志(/etc/rsyslog.d/remote.conf):
template(name=“RemoteLogs” type=“string”
string=“/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log”)
. ?RemoteLogs
重启服务并开放端口
systemctl restart rsyslog ufw allow 514/tcp
/etc/rsyslog.conf(各 VPS 节点客户端)
── rsyslog 客户端配置(各 VPS 节点)──────────────────────────────────────
在 /etc/rsyslog.conf 末尾添加(将 LOG_SERVER_IP 替换为日志服务器 IP):
TCP 转发(推荐,不丢日志):
. @@LOG_SERVER_IP:514
重启使配置生效
systemctl restart rsyslog
验证:在日志服务器上查看是否收到客户端日志
tail -f /var/log/remote/client-hostname/syslog.log
方案 复杂度 搜索能力 适用规模 rsyslog 转发 ⭐ 极简 grep/awk 文本搜索 1-10 台 Loki + Grafana ⭐⭐ 中等 LogQL 标签查询,有 UI 5-50 台 Graylog ⭐⭐⭐ 较复杂 全文搜索,告警集成 10-100 台 ELK Stack ⭐⭐⭐⭐ 复杂 全文索引,Kibana 可视化 50 台以上
对于 1-5 台 VPS 的个人站长,rsyslog 是零成本、零运维的最优解。
## ❓ 常见问题解答
journalctl 和 /var/log/syslog 记录的内容一样吗?该看哪个?
大部分内容相同,但不完全一样。默认配置下,systemd Journal 的日志会通过 rsyslog 转发写入 `/var/log/syslog`,因此高度重合。差别:Journal 额外记录了进程的完整元数据(PID、UID、cgroup),`syslog` 文本文件不含这些;某些服务直接写 stdout/stderr 且不经 syslog,只在 Journal 有记录;而应用程序(Nginx、MySQL)则直接写文本文件,Journal 不含这些。**推荐策略**:排查 systemd 服务(Nginx、sshd)用 `journalctl -u 服务名`;分析攻击流量、统计日志用 `grep/awk` 处理文本文件。两者互补,不必选一。
/var/log/journal 占用大量磁盘空间,如何安全清理?
先运行 `journalctl --disk-usage` 和 `journalctl --list-boots` 确认占用及需要保留的故障窗口。`--vacuum-time`、`--vacuum-size` 会删除已归档日志,可能同时删除重启、入侵或 OOM 证据;事故处理中应先导出相关时间段或保存快照。长期限制宜写入 `/etc/systemd/journald.conf.d/*.conf`,容量应结合磁盘、合规和排错周期确定,不能为所有小内存 VPS 固定推荐同一个数值。
如何判断 auth.log 里的 "Accepted" 是合法登录还是已被入侵?
排查步骤:① 从 `journalctl -u ssh` 或发行版认证日志筛选 Accepted,核对账号、认证方式、来源和时间;② 用 `last -ai` 与云平台审计记录交叉验证;③ 陌生公钥登录不只可能是私钥泄漏,也可能来自被植入的 `authorized_keys`,应先隔离入口、保存日志和主机快照,再轮换密钥、检查授权文件与持久化项;④ 用 `sshd -T` 核对最终生效配置。不要先用宽泛的 `pkill` 清场,以免中断响应会话并丢失现场。
Nginx error.log 大量出现 "no live upstreams",如何彻底解决?
排查路径:① 确认后端服务状态:`systemctl status php8.3-fpm`,若停止重启即可;② 确认监听端口:`ss -tlnp | grep :9000`,确认 upstream 配置的地址端口与实际一致;③ 若用 Unix Socket(如 `/run/php/php8.3-fpm.sock`),确认 socket 文件存在且权限正确;④ 查 PHP-FPM 日志:`journalctl -u php8.3-fpm -n 50`,常见原因:OOM 触发进程被杀、`pm.max_children` 过小导致进程耗尽。**根治**:根据可用内存合理设置 `pm.max_children`(每个 PHP worker 约 50-80MB),并用 Systemd `MemoryMax` 限制上限。
dmesg 出现磁盘 I/O 错误,是硬盘要坏了吗?如何判断?
不同错误含义不同:`Buffer I/O error on device` 可能是坏道或控制器问题;`EXT4-fs error` 是文件系统损坏,通常由突然断电引发;`SCSI error: return code = 0x08000002` 是 SCSI 控制器超时,VPS 上常见,可能是虚拟化平台共享存储问题而非物理磁盘坏。**诊断**:`smartctl -a /dev/sda`(需安装 smartmontools)查看 SMART 数据,重点看 Reallocated_Sector_Ct(坏扇区重分配数,非零则有坏道)和 Current_Pending_Sector。若在 VPS 上出现 I/O 错误,**立即做全量备份**,然后联系商家迁移,不要等待。
truncate 清空 Nginx 日志后会影响正在运行的 Nginx 吗?
`truncate` 通常不会停止 Nginx 写入,但会立即销毁现有日志内容,因此不应作为常规清理或事故响应的第一步。先导出相关时间段并检查现有 logrotate 规则,再通过轮转让 Nginx 重新打开日志文件。若磁盘已满,只释放恢复服务所需的最小空间,同时记录删除内容;直接 `rm` 已打开日志还可能形成 deleted-but-open 文件,可用 `lsof +L1` 定位。
GoAccess 生成的 HTML 报告放到网站上公开访问有没有安全风险?
有明显隐私风险——报告含所有访客 IP 和访问路径,不应公开。推荐做法:① IP 白名单:Nginx 限制只有您自己的 IP 才能访问报告路径;② HTTP Basic Auth:为报告页面添加 `auth_basic` 密码保护;③ 最简单:输出到 `/tmp/`,用 `scp` 下载到本地查看,或通过 SSH 隧道(`ssh -L 8080:127.0.0.1:7890 server`)在本地安全访问。实时 WebSocket 模式绑定到 `127.0.0.1`,再用 SSH 端口转发访问是最安全的实时方案。
如何自动化日志分析,让异常主动通知我而不是手动去查?
结合第 11 篇(automation-scripts)的 Webhook 通知函数,写 Cron 定时日志巡检脚本:① 每 5 分钟统计最近 5 分钟内的 502 数量,超过阈值推送企业微信告警;② 每分钟 `journalctl -k --since "1 min ago" | grep -i oom`,发现 OOM 立即告警;③ 每分钟监控 `auth.log` 中 "Accepted" 记录,来源 IP 不在白名单则立即推送。更完善的方案:部署 **Grafana + Loki**——Loki 是轻量级日志聚合系统,1GB 内存的 VPS 也能运行,通过告警规则实现分钟级异常检测并 Webhook 通知,比 ELK 轻量得多。
本篇学完后,下一步应该如何继续?与后续篇章有什么关联?
按基础运维 30 篇路径,**第 12 篇(本篇,logs-and-troubleshooting)→ 第 13 篇(server-control-panels)→ 第 14 篇(web-server-setup)**是从系统运维到应用部署的关键跨越。关联逻辑:第 13 篇的可视化面板(1Panel/宝塔)会把本篇的 Nginx 日志分析做成图形界面,后台即可查看流量统计和错误趋势;第 14 篇的 Nginx 原生搭建中,本篇学到的 `journalctl -u nginx`、`error.log` 分析和 502 排查,将成为调试虚拟主机配置的核心技能。**至此,整个"系统与安全"系列(第 7-12 篇)构成完整体系**:磁盘管理 → 系统调优 → 防火墙 → 安全加固 → 自动化 → 日志分析,掌握后无惧任何系统级故障。
服务器被入侵后日志可能被删除,如何保护日志完整性?
获取 root 权限的攻击者通常也能修改本机日志属性,因此 `chattr +a` 只能防误操作,不能建立可信取证边界,还可能干扰 logrotate。更可靠的做法是把关键日志实时发送到权限隔离的远端,并在接收端设置独立凭据、保留策略、访问审计和不可变或对象锁存储;定期测试查询与恢复。云端日志和对象存储也必须与受保护主机使用不同权限域,避免同一凭据泄漏后被一起删除。
## 🚀 下一步行动
日志体系掌握之后,接下来进入应用部署阶段:
[ 🖥️
#### 可视化管理面板
1Panel / aaPanel 图形化操作:网站、数据库、日志查看一屏搞定,无需记忆命令。
开始学习 ](/guides/server-control-panels)[ 🌐
#### Web 服务器搭建
Nginx / Apache 原生安装与虚拟主机配置,结合本篇日志知识快速排查 502/404 问题。
开始学习 ](/guides/web-server-setup)[ ⭐
#### VPS 推荐榜单
查看 VPS 实测与服务商索引,先看结论再去官网。
查看推荐 ](/vps-recommendations)[ 📚
#### 浏览更多教程
继续探索服务器安全、网站搭建、性能优化和 AI 环境主题。
探索教程 ](/guides)
读完后建议
先验证,再选择 把判断落到具体选择
准备购买 VPS 时,先对照推荐榜单和真实测评确认线路、价格、用途与风险;只是继续学习,可以回到教程索引按主题往下看。
[ 查看推荐榜单 ](/vps-recommendations) [ 回到教程索引 ](/guides)