CPU 使用率飙升到 100%(资源)

现象:服务器变慢,页面响应超时,用户投诉

  • 1

    运行 tophtop

    实时查看所有进程的 CPU 占用排行。按 P 键按 CPU 降序排列,找到占用最高的进程和它的 PID(进程ID)。

  • 2

    ps aux | grep [PID] 查进程详情

    确认这是哪个程序、哪个用户启动的、启动参数是什么,从而判断它是业务进程还是陌生进程。

  • 3

    strace -p [PID] 看系统调用

    如果是业务进程,strace 能看到它在反复做什么操作(如死循环读文件、死循环计算),帮助定位代码问题。

  • 4

    判断是否是挖矿木马

    如果进程名陌生、用户是 nobody/www-data 、或路径在 /tmp 下,高度怀疑是入侵植入的挖矿程序。立刻 kill -9 [PID] 并排查入侵路径。

根本原因分三类:① 代码 bug(死循环)② 流量突增(正常业务压力)③ 被入侵(挖矿)。排查顺序就是从"是否认识这个进程"开始。


服务被 OOM Killer 杀掉(资源)

现象:服务突然挂掉,日志末尾是 Killed,没有异常堆栈

  • 1

    运行 dmesg | grep -i "oom"

    dmesg 是内核日志。OOM Killer 是 Linux 内核在内存不足时主动杀进程的机制,它会在内核日志里留下记录,说明杀了哪个进程、当时内存状态。

  • 2

    查看 /var/log/messagesjournalctl -k | grep -i oom

    systemd 系统用 journalctl,传统系统看 /var/log/messages,两者都能找到 OOM 事件的详细记录。

  • 3

    确认是内存泄漏还是配置不足

    free -h 查总内存。如果内存本来就小、业务数据量大 → 加内存或加 Swap。如果内存够但进程越占越多 → 代码内存泄漏,需要 profiling 排查。

  • 4

    临时加 Swap 缓解:fallocate -l 2G /swapfile

    Swap 是用磁盘模拟内存,速度慢但能防止 OOM。Java 服务尤其容易吃内存,临时加 Swap 能买时间排查,但不是根本解法。

为什么日志只有 "Killed" 没有报错?因为进程是被内核从外部强杀的(SIGKILL),进程本身来不及写任何东西就没了。这是 OOM 的典型特征。

磁盘满了但 du 找不到大文件(资源)

现象:df 显示 100%,服务写入失败,但 du -sh /* 加起来对不上

  • 1

    运行 df -h 确认哪个分区满了

    df 显示的是文件系统实际占用,du 显示的是目录里可见文件的大小。两者不一致时,说明有"幽灵空间"。

  • 2

    运行 lsof | grep deleted

    这是核心原因:文件被 rm 删除后,如果还有进程(如 Nginx、Java)持有这个文件的句柄(文件描述符),inode 不会释放,空间也不会还给操作系统。lsof 能看到这些"已删除但仍占空间"的文件。

  • 3

    重启相关进程来释放句柄

    对持有这个 deleted 文件的进程执行 systemctl restart [服务名],进程重启后句柄释放,空间才真正还给 OS。

  • 4

    日常:用 du -sh /* | sort -rh | head -20 找真实大目录

    从根目录往下逐层找最大目录,通常是 /var/log(日志堆积)或 /var/lib/docker(容器镜像)。

陷阱:很多人以为 rm 就彻底删了。实际上 Linux 的删除只是"断开文件名和 inode 的链接",只要还有进程持有 fd,数据和占用空间就不会消失。


本地通但外部端口访问不了(网络)

现象:curl localhost:80 成功,但外网 IP 访问 80 端口超时

  • 1

    确认服务监听地址:ss -tlnp | grep 80

    关键点:0.0.0.0:80 表示监听所有网卡(外网可达),127.0.0.1:80 表示只监听本机回环(外网完全访问不到)。Nginx 默认监听 0.0.0.0,但配置错误时可能只绑定了本地。

  • 2

    检查系统防火墙:firewall-cmd --list-alliptables -L

    即使服务监听了 0.0.0.0,系统防火墙也可能把外部流量挡在外面。需要确认 80/443 端口在防火墙规则里是放行的。

  • 3

    检查云平台安全组

    腾讯云、阿里云等有"安全组"是在网络层面的防火墙,比系统防火墙更靠前。安全组没开放端口,数据包根本到不了服务器,所以系统内 iptables 放行也没用。

  • 4

    从外部测试端口:telnet [公网IP] 80

    如果 telnet 直接拒绝(Connection refused)= 到了服务器但端口没开;如果超时(timeout)= 安全组/网络层拦截了,根本没到服务器。两种现象对应不同的排查方向。

排查链:监听地址 → 系统防火墙 → 云安全组,三层都要检查,卡在哪层现象略有不同。


疑似 DDoS / SYN Flood 攻击(网络)

现象:netstat 大量 SYN_RECV,服务响应极慢甚至无响应

  • 1

    确认攻击:netstat -an | grep SYN_RECV | wc -l

    正常情况下 SYN_RECV 数量极少。SYN Flood 的原理是攻击方大量发 SYN 包但不完成三次握手,服务器队列被占满,正常连接进不来。

  • 2

    开启 SYN Cookie:sysctl -w net.ipv4.tcp_syncookies=1

    SYN Cookie 是内核级防御。开启后,服务器不会为半开连接分配资源,而是用一个加密 cookie 来验证,使 SYN Flood 失效。

  • 3

    用 iptables 限速或封攻击 IP

    iptables -A INPUT -p tcp --syn -m limit --limit 100/s -j ACCEPT 限制每秒新 SYN 包数量,超出的丢弃。如果攻击来自少数固定 IP,可以直接 DROP 封掉。

  • 4

    大流量攻击联系云厂商开启 DDoS 防护

    如果攻击流量超过服务器带宽(比如几十 Gbps 的流量攻击),服务器本身无法处理,必须在上游进行流量清洗(腾讯云 DDoS 高防 IP 等)。

SYN Flood 是四层攻击,iptables 在系统内处理,如果带宽已经被打满,iptables 规则也来不及生效。大规模攻击必须靠上游清洗。


Nginx 返回 502 Bad Gateway(服务)

现象:用户看到 502,Nginx 进程是运行的,之前好好的

  • 1

    理解 502 的含义

    502 = 网关错误。Nginx 本身正常,但它作为反向代理去连后端服务(Java/Python/PHP)时失败了。原因要去后端找,不是 Nginx 的问题。

  • 2

    检查后端服务是否在运行

    systemctl status [后端服务名]ps aux | grep java。后端进程崩溃是 502 最常见的原因。

  • 3

    查后端服务的日志

    进程在但 502 也可能发生(如后端启动了但端口没监听成功、后端代码抛了异常导致无法响应)。日志里会有具体报错。

  • 4

    核对 Nginx upstream 配置:nginx -t

    确认 nginx.conf 里 proxy_pass 指向的地址和端口与后端实际监听的一致。端口写错(如后端跑 8080,配置写了 8081)也会 502。

区分常见状态码:404 = 资源不存在(Nginx 正常);502 = 后端挂了(找后端);504 = 后端太慢超时(性能问题);500 = 后端代码报错(看后端日志)。


Crontab 定时任务没有执行(服务)

现象:写了 cron 表达式,到时间了任务没跑,也没报错

  • 1

    确认 cron 服务在运行:systemctl status croncrond

    cron 服务本身没启动,所有任务都不会执行。Ubuntu 叫 cron,CentOS 叫 crond,名字不同。

  • 2

    检查 cron 表达式语法

    cron 表达式是 分 时 日 月 周 五个字段。常见错误:* * * * * 是每分钟,0 2 * * * 是每天凌晨2点。可以用 crontab.guru 网站验证。

  • 3

    检查脚本是否有执行权限:chmod +x /path/to/script.sh

    cron 不会像手动运行一样报"Permission denied",它只是静默失败。脚本没有 x 执行权限时任务就是不跑。

  • 4

    在 cron 里用绝对路径

    cron 的运行环境没有普通 shell 的 PATH(比如没有 /usr/local/bin)。脚本里写 python3 可能找不到,要写成 /usr/bin/python3

  • 5

    把输出重定向到日志:cmd >> /tmp/cron.log 2>&1

    cron 默认不输出任何东西,也不报错。加上日志重定向,下次出问题就能看到究竟发生了什么。这是最重要的 debug 手段。

新手最常踩的坑:脚本在终端里手动运行没问题,cron 里就是不跑。99% 是路径问题(PATH 环境变量不同)或权限问题。

SSH 被大量陌生 IP 爆破(安全)

现象:/var/log/auth.log 里大量 Failed password for root,来自不同 IP

  • 1

    安装 fail2ban:apt install fail2ban

    fail2ban 监控日志,某个 IP 在短时间内连续登录失败 N 次,就自动用 iptables 封禁它。自动化处理,不用人工盯着。

  • 2

    改 SSH 端口(改成非 22 的高位端口)

    互联网上大量自动扫描工具只扫 22 端口。改成如 12345,扫描工具就找不到了,爆破流量立刻减少 99%。治标但有效。

  • 3

    禁用密码登录,改用密钥:PasswordAuthentication no

    密钥登录的原理是非对称加密。攻击者就算知道用户名,没有私钥就无法登录,爆破密码完全无效。这是最根本的防御措施。(你已经在做了)

  • 4

    在 sshd_config 里禁止 root 直接登录:PermitRootLogin no

    攻击者通常第一个试 root。禁止 root 远程登录后,即使密码泄露也无法直接拿到最高权限,需要先登普通用户再 sudo。

防御纵深原则:改端口(减少扫描)+ 密钥登录(爆破无效)+ fail2ban(自动封 IP)+ 禁 root 登录(降低危害),四层叠加,远比只做一层安全。