服务器突然无法访问怎么办?从网络、系统到应用逐层排查

服务器"突然打不开了",是运维里最常见也最容易慌的一类故障。用户的说法往往是"网站挂了""连不上了""一直转圈",但同样是打不开,背后的原因可能差得很远:可能是运营商线路抖动,可能是安全组把端口封了,可能是系统负载炸了,可能是 Nginx 进程崩了,也可能是后端数据库卡死了。如果没有章法,很容易变成"改一下这个、重启一下那个",越弄越乱。

这篇文章要给的是一套分层排查的方法论:把"无法访问"拆成网络层、系统层、服务层、应用层、数据库层五个层次,从外往里一层一层缩小范围,每一步都用具体命令给出证据。读完你应该能做到:接到报警后不慌不忙,先判断"是哪一层的问题",再用最短的路径定位到根因,而不是靠猜。

需要强调的是,分层排查的核心不是命令本身,而是顺序和思路。从下往上还是从上往下其实都可以,关键是每一层都要有明确的"通过/不通过"判据,找到第一个不通过的层次,再往下深挖。下面按"从外到内"的顺序展开。

一、先搞清楚"访问不了"到底指什么

同样是访问不了,现象的细微差别会直接影响排查方向。动手敲命令之前,先问清楚或者自己确认几件事:

  • 范围:是所有人访问不了,还是只有你访问不了?只有个别人打不开,通常是本地网络、DNS 缓存或者运营商线路的问题;所有人都打不开,才是服务器侧的问题。
  • 方式:是完全连不上(连接超时/拒绝),还是能连上但页面报错(502、504、500)?前者偏网络和进程,后者偏服务和应用。
  • 协议:是 HTTP 打不开,还是 SSH 也连不上?如果 SSH 也进不去,问题多半在网络层或系统层;如果 SSH 正常但网站 502,那基本锁定在服务层或应用层。
  • 时间点:是刚刚突然发生的,还是一直如此?结合"最近有没有改过配置、发过版本、加过数据",能快速缩小范围。

一个实用的技巧是:先用自己的手机 4G/5G 网络访问一次。如果手机流量能打开、公司网络打不开,说明服务器没问题,是本地出口或 DNS 的问题;如果手机也打不开,才需要上服务器排查。这一步能省掉大量无效劳动。

二、网络层:先确认"能不能通"

网络层要回答的问题只有一个:数据包能不能到达服务器、端口是不是开着。

# 1. 先看域名解析是否正常,确认解析到的 IP 是不是你以为的那台
dig +short www.example.com
nslookup www.example.com

# 2. ping 通不通,看丢包和延迟
ping -c 4 www.example.com

# 3. 测端口是否可达(telnet 或 nc 都行,nc 更通用)
telnet 203.0.113.10 80
nc -zv 203.0.113.10 80
nc -zv -w 3 203.0.113.10 443     # -w 指定超时秒数,避免卡死

# 4. 从 HTTP 层面看返回了什么
curl -I -m 10 http://www.example.com
curl -v -m 10 https://www.example.com   # -v 打印握手细节,排查 TLS/跳转很有用

判读方式:

现象 含义 排查方向
ping 不通但业务能用 ICMP 被禁,正常 不代表故障,忽略
ping 通、端口不通 服务未监听或防火墙拦截 系统层、防火墙
端口拒绝(Connection refused) 能到主机,但没人监听该端口 服务未启动或端口改错
连接超时(timeout) 包被丢弃,防火墙/安全组/线路问题 安全组、firewalld/ufw、iptables
能连上但返回 502/504 网络通,问题在后端 服务层、应用层

最常见的坑是"安全组没放行"。云服务器的安全组是独立于操作系统防火墙的一层,很多人在服务器里 systemctl status firewalld 看是关的,就以为没防火墙,结果云控制台的安全组把 80/443 拦了。排查时务必把云安全组、系统防火墙(firewalld/ufw/iptables)、应用监听地址三样分开确认。

如果 ping 不通而且确定不是 ICMP 被禁,可以用 mtr 或 traceroute 看断在哪一跳,判断是本地出口、中间线路还是机房的问题:

mtr -rw -c 20 www.example.com     # 融合 ping 和 traceroute,持续采样更准
traceroute www.example.com

三、系统层:看资源是否被耗尽

网络通了、端口也开着,但服务就是慢或者进不去,先把系统本身的资源看一遍。系统层要排查的是:负载、CPU、内存、磁盘、进程数、inode。

# 负载与运行时长:看 1/5/15 分钟平均负载
uptime

# CPU 与内存总览,按 M 键可按内存排序,按 P 按 CPU 排序
top -bn1 | head -20
free -h

# 磁盘空间和 inode(inode 用尽同样会导致写不进去、服务异常)
df -h
df -i

# 磁盘 IO 是否卡住
iostat -x 1 3            # 需 sysstat:yum install sysstat / apt install sysstat
iotop -oP                # 需 iotop 包,看谁在疯狂读写

# 进程数、句柄数是否触顶
ps aux | wc -l
cat /proc/sys/kernel/pid_max

# 找出吃资源最多的进程
ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10

几个关键判据(经验值,视机器规格而定):

  • 负载:平均负载持续高于 CPU 核数(nproc 查看),说明有排队。4 核机器负载长期 > 4 就要警惕,> 8 基本就是过载。
  • 内存:free -h 的 available 接近 0,且 swap 在被大量使用,往往伴随 OOM 风险。
  • 磁盘:df -h 使用率超过 90% 要清理;df -i inode 使用率 100% 时,即使还有空间也写不进新文件,报错通常是 No space left on device。
  • IO:iostat 里 %util 长期贴着 100%,说明磁盘是瓶颈。

如果发现某个进程把 CPU 或内存吃满,先别急着 kill,先确认它是不是业务进程、能不能重启。正确做法是记录 PID、进程名、启动命令(ps -fp 、ls -l /proc//exe),再决定是限流、重启还是扩容。

四、服务层:进程在不在、端口听没听

系统资源没问题,就要看具体服务(Nginx、MySQL、Tomcat、Redis 等)的进程和端口状态。这是"能连上但 502/连不上"的高发区。

# 看服务状态(systemd 管理)
systemctl status nginx
systemctl status mysqld        # Rocky/CentOS 上是 mysqld,Ubuntu 上可能是 mysql
systemctl is-active nginx      # 只返回 active/inactive,适合脚本判断

# 查看最近日志(journalctl,systemd 系统通用)
journalctl -u nginx -n 100 --no-pager
journalctl -u nginx --since "1 hour ago" -p err

# 看端口有没有在监听、被谁监听
ss -lntp                       # 列出 TCP 监听端口及对应进程
ss -lntp | grep ':80'
ss -lnup | grep ':53'          # udp 端口

# 老系统没有 ss 时用 netstat(net-tools 包)
netstat -lntp | grep ':80'

重点看两件事:进程是否存活、端口是否在监听。

  • 进程不在、systemctl status 显示 failed 或 activating (auto-restart):去看日志找崩溃原因,不要无脑 systemctl restart,否则可能反复崩。
  • 进程在、但端口没监听:可能是配置里绑定了特定 IP(比如只听了 127.0.0.1),外部访问不到;也可能是启动到一半卡住了。
  • 进程在、端口也在听,但外部访问不了:多半是防火墙或安全组。
# 典型情况:Nginx 只监听了 127.0.0.1,外部访问不到
ss -lntp | grep ':80'
LISTEN 0 511 127.0.0.1:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
# 注意 127.0.0.1 和 0.0.0.0 的区别,前者只接受本机连接

如果服务反复重启,看 systemctl status 输出里的 Restart= 和日志里的时间线;如果是被系统杀掉的,可能是 OOM(后面第六篇专门讲)。

五、应用层:看应用自身日志和依赖

服务进程、端口都正常,但访问还是报错,就要进到应用这一层。这里看的是应用自己的日志、配置文件、依赖服务。

# 应用日志在哪?先看配置和常见路径
ls -lh /var/log/nginx/
ls -lh /var/log/myapp/
tail -f /var/log/nginx/error.log
tail -n 200 /var/log/myapp/app.log | grep -i error

# 如果应用是 systemd 服务,stdout 会进 journal
journalctl -u myapp -f

# 从服务器本地直接请求,绕过外网干扰,看真实返回
curl -v http://127.0.0.1:8080/health
curl -v -H "Host: www.example.com" http://127.0.0.1/

应用层常见原因:配置写错(改完没 reload)、依赖服务连不上(数据库/Redis/MQ)、代码 bug、磁盘权限不足、证书过期(HTTPS 场景)。

证书过期是特别容易忽略的一类"全站突然打不开",因为它是按时触发的。用 curl -v 或下面命令能看到证书到期时间:

echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null \
  | openssl x509 -noout -dates

六、数据库层:最后确认后端是否响应

如果前端表现是接口超时、页面转圈、502/504,而 Nginx 和应用进程都正常,那根因很可能在后端数据库。数据库慢会一路传导到用户侧。

# MySQL 是否还在监听、能否登录
mysqladmin -uroot -p status
mysql -e "SHOW PROCESSLIST;"        # 看有没有大量卡住的查询
mysql -e "SHOW ENGINE INNODB STATUS\G" | head -60   # 看锁等待、死锁

# 从应用服务器测数据库端口
nc -zv 10.0.0.5 3306

# Redis 是否响应
redis-cli ping                      # 返回 PONG 即正常
redis-cli info memory | grep used_memory_human

判读要点:SHOW PROCESSLIST 里如果有大量 Sending data、Locked 状态的连接,通常是有慢 SQL 或者表被锁住;连接数打满(接近 max_connections)会导致新连接直接被拒。这时不要盲目重启数据库(会丢事务、影响更大),先看慢查询、看锁、看连接数。

七、一张分层排查顺序表

把上面的内容压缩成一张表,遇到"无法访问"按顺序从上往下走,找到第一个不通过的层次即可:

顺序 层次 关键命令 判据 常见根因
1 客户端/本地 手机流量访问、换网络 换网络能开 本地 DNS、出口线路
2 网络/DNS dig、ping、nc -zv、curl -I 端口可达、返回预期状态码 DNS 解析、安全组、线路
3 防火墙 firewall-cmd、ufw status、iptables -L 端口放行 安全组+系统防火墙双重拦截
4 系统资源 uptime、free -h、df -h、df -i 负载/内存/磁盘/inode 正常 过载、内存耗尽、磁盘满
5 服务进程/端口 systemctl status、ss -lntp 进程 active、端口 LISTEN 进程崩溃、监听地址错
6 应用 tail 日志、curl 127.0.0.1 本地请求正常返回 配置错、依赖不通、证书过期
7 数据库 SHOW PROCESSLIST、nc -zv 3306 连接正常、无大量卡住查询 慢 SQL、锁等待、连接打满

绝大多数"无法访问"都能在这七步内定位。养成"先分层、再造证据"的习惯,比记住一堆零散命令更重要。

八、几个必须注意的风险点

排查过程中会用到一些有副作用的命令,动手前想清楚:

  • 重启服务:systemctl restart 会中断现有连接。生产环境先确认有没有正在处理的任务,能 reload 就 reload(Nginx、PHP-FPM 支持平滑重载),不要无脑 restart。
  • 改防火墙:改之前先留一条能进的退路,尤其是 SSH 端口。远程改防火墙要用 firewall-cmd --add-* --timeout=60 临时生效先测试,确认能进再永久保存。
  • kill 进程:先想清楚这个进程是不是业务进程、杀掉会不会丢数据。数据库、MQ 这类有状态服务尤其要谨慎,优先用服务管理命令而非 kill -9。
# 防火墙临时放行示例(60 秒后自动失效,安全测试)
# RHEL/CentOS/Rocky
firewall-cmd --add-port=80/tcp --timeout=60
firewall-cmd --permanent --add-port=80/tcp && firewall-cmd --reload   # 永久生效
# Debian/Ubuntu
ufw allow 80/tcp
ufw status verbose

常见问题

Q:服务器 ping 不通,但网站能打开,是不是有问题?
不是问题。很多云环境默认禁用 ICMP,ping 不通是正常的。判断连通性应该用 nc -zv <端口> 测端口,而不是靠 ping。

Q:安全组放行了,为什么还是连不上?
很可能是系统防火墙(firewalld/ufw/iptables)也拦着。云安全组和系统防火墙是两层,要分别确认。用 firewall-cmd --list-all 或 ufw status verbose 看系统侧,用 iptables -L -n 看底层规则。

Q:SSH 都进不去了,怎么办?
先确认是 SSH 端口不通还是口令错误。在能 ping 通的前提下用 nc -zv 22 测端口。如果端口不通,去云控制台用 VNC/救援终端登录,检查 sshd 状态和防火墙。如果端口通但登不上,看 journalctl -u sshd 或 /var/log/secure(Debian/Ubuntu 是 /var/log/auth.log)。

Q:能连上但页面一直转圈,该看哪一层?
页面转圈通常是后端响应慢,直接跳到第五、六层看应用日志和数据库。先用 curl -m 10 从本地请求接口,看是否超时,再去看慢 SQL 和锁等待。

Q:磁盘还有空间,为什么写文件报 No space left on device?
大概率是 inode 用尽了。用 df -i 查看,如果 inode 使用率 100%,需要找出大量小文件的目录(常是日志、缓存、session 文件)并清理。

总结

"无法访问"要先分层,再找证据。顺序是:客户端 → 网络/DNS → 防火墙 → 系统资源 → 服务进程/端口 → 应用 → 数据库,找到第一个不通过的层次深挖。

判断连通性用 nc -zv 测端口,不要只靠 ping;云安全组和系统防火墙是两层,必须分别确认。

服务层重点看进程是否存活、端口是否 LISTEN,注意监听地址是 0.0.0.0 还是 127.0.0.1;应用层重点看日志和本地 curl;后端慢就查数据库的连接数、慢查询和锁等待。

涉及重启服务、改防火墙、kill 进程等操作前,先评估影响、留好退路,能用 reload 和 --timeout 临时规则就不要用破坏性操作。