Linux进程连不上远端服务?用ss和lsof按PID检查连接状态
要判断 Linux 进程为什么连不上远端服务,先确认“发起连接的到底是不是目标进程”,再查看该 PID 对应的本地地址、远端地址和 TCP 状态。ss 适合快速查看内核当前连接及监听状态,lsof 可以从进程文件描述符角度确认网络套接字;两者结合,能够把问题初步分到应用绑定、主机防火墙、安全组、NAT或远端服务未响应等范围。
实际排查时,先按 PID 检查进程是否存在网络连接,再判断结果是 ESTAB、SYN-SENT、LISTEN 还是完全没有套接字。ESTAB 只能证明 TCP 三次握手已完成,不代表应用层请求一定成功;SYN-SENT 通常说明连接请求发出后没有完成握手,需要继续核对路由、防火墙、安全组、NAT和远端监听状态。
准备条件
以下命令适用于常见 Linux 发行版,依赖:
ss:通常由iproute2提供。lsof:部分精简系统可能未预装。ps、ip、getent:用于确认进程、路由和名称解析。systemctl、journalctl:仅适用于使用 systemd 管理服务的系统。
先准备目标 PID、远端主机和端口。示例中使用 PID 1234、远端地址 10.20.30.40:5432,请替换为实际值。
PID=1234
REMOTE_HOST=db.example.internal
REMOTE_IP=10.20.30.40
REMOTE_PORT=5432
确认 PID 没有填错:
ps -o pid,ppid,user,etime,stat,cmd -p "$PID"
如果只知道服务名,可以先查找进程:
pgrep -af '应用名称或关键启动参数'
对于 systemd 服务,也可以查看主进程 PID:
systemctl show -p MainPID --value app.service
没有 root 权限时,ss -p 和 lsof 可能无法显示其他用户进程的 PID、程序名或文件描述符。出现信息不完整时,使用 sudo 重复执行,不要仅凭空白结果判断进程没有连接。
第一步:确认进程是否持有网络套接字
使用 ss 按 PID 查看 TCP 连接
sudo ss -Hntp | grep -F "pid=$PID,"
参数含义:
-H:不显示表头,便于脚本处理。-n:直接显示 IP 和端口,不进行反向解析。-t:只看 TCP。-p:显示关联的进程、PID和文件描述符。
典型输出可能类似:
ESTAB 0 0 192.168.1.20:41876 10.20.30.40:5432 users:(("app",pid=1234,fd=17))
这表示 PID 1234 的进程通过本地 192.168.1.20:41876 连接到 10.20.30.40:5432,当前 TCP 状态为 ESTAB。
查看该进程的 UDP 套接字:
sudo ss -Hnup | grep -F "pid=$PID,"
UDP 没有 TCP 那样完整的握手状态。输出中的 UNCONN 不等于网络一定不可达,只能说明该套接字没有处于 TCP 式连接状态。对于 UDP,需要结合应用日志、抓包或远端服务响应判断。
使用 lsof 从文件描述符确认连接
sudo lsof -nP -a -p "$PID" -i
分别查看 TCP 和 UDP:
sudo lsof -nP -a -p "$PID" -iTCP
sudo lsof -nP -a -p "$PID" -iUDP
典型 TCP 输出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
app 1234 app 17u IPv4 98765 0t0 TCP 192.168.1.20:41876->10.20.30.40:5432 (ESTABLISHED)
重点核对以下字段:
PID:是否为目标进程。FD:套接字对应的文件描述符。TYPE:是 IPv4 还是 IPv6。NAME:本地地址、远端地址和连接状态。- 远端端口:是否确实是业务要求的端口,而不是配置中的旧端口。
ss 反映内核当前网络状态,刷新速度快;lsof反映进程打开的文件描述符。若两者结果不一致,先考虑连接变化、权限不足、网络命名空间不同或进程刚好关闭了短连接。

第二步:区分 TCP 状态,确定故障边界
可以用下面的命令持续观察一个短时间窗口,避免短连接刚建立就消失:
for i in $(seq 1 10); do
date -Is
sudo ss -Hntp | grep -F "pid=$PID," || true
sleep 1
done
常见状态与判断方式如下:
| 观察结果 | 正常与异常分界 | 优先检查方向 |
|---|---|---|
ESTAB | TCP 握手已完成,网络层连接基本建立 | 应用协议、认证、TLS、请求超时和远端服务日志 |
SYN-SENT | 本机发出 SYN,但暂未收到 SYN-ACK | 路由、主机出站策略、安全组出站、NAT、远端入口和远端监听 |
SYN-RECV | 本机收到连接请求,但握手未完成 | 本机回包路径、防火墙状态规则、对端回包和中间设备 |
TIME-WAIT | 本地连接已关闭后的正常保留状态 | 通常不是当前连不上;连接创建过于频繁时再检查端口和资源 |
CLOSE-WAIT | 对端已关闭,本地进程尚未关闭套接字 | 应用没有及时释放连接,重点看应用代码或连接池 |
| 没有任何记录 | 当前没有被观测到的网络套接字 | PID、配置、DNS、短连接时机、网络命名空间和权限 |
UDP UNCONN | UDP 套接字存在,但没有 TCP 式连接状态 | 应用发送逻辑、返回包、服务端口和抓包结果 |
SYN-SENT 是端口连接排查中的重要分界点。它说明应用至少创建了 TCP 连接并尝试发起请求,但不能单凭这一行确定是本机防火墙、云安全组、NAT还是远端服务拒绝。需要继续执行后续检查。
如果显示 ESTAB,但应用仍报“连接失败”,网络握手已经成功,故障通常发生在握手之后,例如远端协议不匹配、认证失败、TLS协商失败、连接池配置错误或应用等待响应超时。此时不要反复修改端口放行规则。
第三步:检查本机是否正确监听和绑定
如果故障是“其他机器连不上本机服务”,先查看监听状态:
sudo ss -lntp
按端口筛选:
sudo ss -lntp 'sport = :8080'
使用 lsof 交叉确认:
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
也可以按 PID 查看监听套接字:
sudo ss -Hlnpt | grep -F "pid=$PID,"
sudo lsof -nP -a -p "$PID" -iTCP -sTCP:LISTEN
重点区分以下绑定结果:
127.0.0.1:8080:只接受本机回环接口连接,远程机器无法直接访问。192.168.1.20:8080:只绑定指定网卡地址,访问其他网卡地址或公网映射地址可能失败。0.0.0.0:8080:监听所有 IPv4 网卡,但仍可能被本机防火墙、安全组或NAT阻断。[::]:8080:监听 IPv6;是否同时接受 IPv4 取决于系统的 IPv6 双栈设置。- 没有监听记录:应用可能没有启动成功、实际使用了其他端口、绑定失败,或者监听套接字位于其他网络命名空间。
检查本机地址和路由:
ip -br addr
ip route
如果应用绑定了一个已经不存在的地址,常见表现是启动时报 Cannot assign requested address,或者服务启动后没有对应监听端口。此时查看启动参数和服务配置:
tr '\0' ' ' < /proc/"$PID"/cmdline
echo
如果由 systemd 管理:
systemctl cat app.service
systemctl status app.service --no-pager
journalctl -u app.service -n 100 --no-pager
不要因为看到 0.0.0.0:8080 就认为公网访问一定正常。它只说明应用在本机 IPv4 地址上监听,不能证明云安全组、入口NAT或外部防火墙已经放行。
第四步:核对远端地址、解析和路由
先确认应用使用的域名解析到了哪个地址:
getent ahosts "$REMOTE_HOST"
如果应用配置使用域名,而 ss 中显示的远端 IP 与预期不一致,应继续核对:
- DNS是否解析到了正确地址。
- 应用是否缓存了旧解析结果。
- IPv4和IPv6是否选择了不同路径。
- 远端端口是否与配置一致。
查看到目标 IP 的路由和源地址选择:
ip route get "$REMOTE_IP"
示例结果可能包含:
10.20.30.40 via 192.168.1.1 dev eth0 src 192.168.1.20
这表示系统计划通过 eth0、网关 192.168.1.1,使用源地址 192.168.1.20 访问远端。若路由不存在、接口状态异常,或者源地址不是安全组允许的地址,连接可能停留在 SYN-SENT。
在不影响应用配置的前提下,可以从同一台主机、同一网络命名空间进行 TCP 探测:
nc -vz -w 3 "$REMOTE_IP" "$REMOTE_PORT"
该命令仅用于验证主机到目标端口的基础 TCP连通性,不能证明目标进程使用的配置、认证和应用协议正常。如果系统没有 nc,不要把“命令不存在”误判成端口不通,应使用已有探测工具或直接结合 ss、应用日志和抓包判断。
第五步:检查主机防火墙
主机防火墙需要分别考虑入站和出站方向。访问远端服务时,即使本机没有入站监听,也可能存在出站限制;提供本机服务时,则重点检查入站规则。
优先确认系统实际使用哪套防火墙管理工具,只查看,不要同时修改多套规则:
sudo firewall-cmd --state 2>/dev/null
sudo firewall-cmd --list-all 2>/dev/null
如果使用 UFW:
sudo ufw status verbose
如果使用 nftables:
sudo nft list ruleset
如果系统仍使用 iptables 规则:
sudo iptables -S
sudo iptables -L -n -v
检查时重点看:
- 目标端口和协议是否匹配,例如 TCP
5432与 UDP5432不是同一条规则。 - 规则匹配的接口是否正确,例如只允许
eth0,但流量实际从其他接口进入。 - 源地址或目标地址是否写错。
- 默认策略是否为
DROP或REJECT。 - 出站方向是否限制了远端端口或临时源端口。
- 是否存在按连接状态放行返回包的规则。
DROP通常表现为连接长时间停留在 SYN-SENT或探测超时;REJECT可能较快返回错误,但具体表现还取决于规则和协议。仅凭客户端超时不能直接确认是防火墙丢包。
不要使用 iptables -F、nft flush ruleset 等清空规则的方式“快速测试”,这可能导致远程登录中断、业务端口暴露或整台主机失去访问控制。如果必须临时调整规则,先保存当前规则和管理工具配置,限定源地址、目标端口及测试时间,并记录变更前后的规则;验证完成后删除临时规则或按原配置恢复。
第六步:核对安全组、NAT和入口映射
主机上的 ss 和 lsof 看不到云平台安全组的最终判定,也看不到NAT设备转换后的完整连接。需要按照流量方向核对。
访问远端服务时
流量通常类似:
进程本地地址:临时端口
↓
本机路由和出站防火墙
↓
出口NAT或网关
↓
远端安全组入站规则
↓
远端主机监听端口
重点确认:
- 本机安全组是否允许出站到远端 IP 和目标端口。
- 出口NAT是否存在、是否有可用地址和端口资源。
- 远端安全组入站规则是否允许本机实际的出口公网 IP 或网段。
- 远端服务是否监听在正确的私网或公网地址。
- 中间网络设备是否只允许特定源端口、目的端口或协议。
需要注意,ss 显示的是本机NAT之前的本地地址和临时端口,不能直接证明远端看到的源公网 IP。远端日志、云流日志或出口网关记录更适合确认NAT后的源地址。
外部访问本机服务时
流量通常类似:
客户端
↓
公网地址:公网端口
↓
入口NAT或负载均衡
↓
云安全组和网络访问控制
↓
私网地址:目标端口
↓
应用监听套接字
应逐项核对:
- 公网端口是否映射到正确的私网 IP 和端口。
- 映射协议是否为 TCP,是否误配成 UDP。
- 安全组入站规则的源地址范围是否包含客户端。
- 入口映射后的目标端口是否与
ss -lntp中的监听端口一致。 - 应用是否只绑定了
127.0.0.1。 - 主机防火墙是否允许映射后的入站流量。
如果主机完全看不到来自客户端的连接尝试,优先检查NAT、安全组、网络访问控制和入口地址;如果主机能看到 SYN,但没有形成连接,再检查本机监听状态、防火墙和回包路径。
第七步:用抓包确认数据包走到哪一步
当 ss 长时间显示 SYN-SENT,或者安全组和防火墙规则看起来都正常,可以在限定时间内抓取目标流量。抓包可能包含业务数据和敏感地址,应限制目标、时间和文件权限。
OUT=/tmp/port-check-$(date +%Y%m%d-%H%M%S)
mkdir -m 700 "$OUT"
sudo timeout 30 tcpdump -ni any \
"host $REMOTE_IP and tcp port $REMOTE_PORT" \
-c 50 -w "$OUT/flow.pcap"
如果只需要在终端观察握手,不保存数据包:
sudo timeout 30 tcpdump -ni any \
"host $REMOTE_IP and tcp port $REMOTE_PORT" \
-c 20
常见判断方式:
- 能看到本机发出的
SYN,看不到SYN-ACK:远端未响应,或中间设备丢弃返回包。 - 能看到
SYN和RST:某一端主动拒绝,常见于端口未监听或策略拒绝。 - 能看到完整握手,但应用仍报错:网络连接已经建立,应转向应用协议和日志。
- 完全看不到本机发出的
SYN:进程可能没有真正发起连接、连接尝试尚未发生、目标地址解析错误,或抓包接口和网络命名空间不对。
抓包只用于定位,不要把保存的 .pcap 文件直接上传到公开位置。完成取证后,按组织的敏感信息保留周期处理。
常见失败处理
ss 没有显示 PID 或程序名
先用 root 权限执行:
sudo ss -ntup
sudo lsof -nP -a -p "$PID" -i
如果仍然没有结果,检查 PID 是否属于容器或其他网络命名空间。目标进程存在但主机网络视图中看不到时,可在确认权限和容器管理方式后进入该进程的网络命名空间:
sudo nsenter -t "$PID" -n ss -Hntup
nsenter 只查看网络状态,不会修改配置;但进入错误 PID 可能看到不相关的网络空间,执行前应先用 ps确认目标进程。
没有连接记录,但应用日志显示连接失败
可能原因包括:
- 应用尚未执行到真正的连接代码。
- 连接是短暂创建后立即关闭。
- 应用使用 UDP,检查时只查看了 TCP。
- 应用在另一个容器或网络命名空间中。
- 使用了错误的 PID,例如查看了父进程而不是工作进程。
- DNS解析或配置校验在创建套接字前就已经失败。
应同时采集应用日志、重复执行 ss,并确认启动参数和配置中的远端地址。
只有 SYN-SENT
先按以下顺序处理:

- 用
getent ahosts确认域名解析。 - 用
ip route get确认路由和源地址。 - 查看本机出站防火墙。
- 查看云安全组出站和远端安全组入站。
- 核对出口NAT和远端监听。
- 必要时短时抓包确认是否有
SYN-ACK返回。
不要在没有证据时直接重启应用或修改远端服务端口。重启通常只能清除现有连接,无法修复路由、安全组或NAT问题。
显示 ESTAB,但程序仍然报错
此时 TCP 连接已经建立。重点收集:
sudo lsof -nP -a -p "$PID" -iTCP
sudo ss -Hntpo | grep -F "pid=$PID,"
关注发送队列、接收队列、连接持续时间和应用日志。若握手完成后长时间没有响应,可能是远端应用处理慢、协议不匹配、认证失败或连接池复用异常,而不是端口未开放。
本机有监听,远程仍然连接不上
检查监听地址是否为回环地址,再依次核对:
- 本机防火墙入站策略。
- 云安全组入站规则。
- NAT或负载均衡的目标端口。
- 网络访问控制列表。
- 客户端访问的 IP 是否与实际映射地址一致。
如果本机抓包能看到客户端 SYN,但应用没有回复,优先看监听端口、绑定地址和主机防火墙;如果完全看不到 SYN,优先看安全组、NAT和入口路径。
留证与结果验收
排查结束前,建议在受限目录中保存一次完整现场。下面的命令只读取状态,不修改网络配置:
OUT=/tmp/port-check-$(date +%Y%m%d-%H%M%S)
mkdir -m 700 "$OUT"
{
echo "=== time ==="
date -Is
echo "=== host ==="
hostname
echo "=== process ==="
ps -o pid,ppid,user,etime,stat,cmd -p "$PID"
echo "=== cmdline ==="
tr '\0' ' ' < /proc/"$PID"/cmdline
echo
echo "=== ss by pid ==="
sudo ss -Hntup | grep -F "pid=$PID," || true
echo "=== listening ==="
sudo ss -Hlnpt
echo "=== lsof by pid ==="
sudo lsof -nP -a -p "$PID" -i
echo "=== address ==="
ip -br addr
echo "=== route ==="
ip route get "$REMOTE_IP"
} 2>&1 | tee "$OUT/summary.txt"
验收时至少应得到以下明确结论:
- 目标 PID 与实际业务进程一致。
ss和lsof能看到目标进程的网络套接字,或已经说明为什么没有套接字。- 远端 IP和端口与配置一致。
- 访问远端服务时,连接状态达到
ESTAB,或者已根据SYN-SENT定位到具体网络边界。 - 提供本机服务时,监听端口、协议和绑定地址符合要求。
- 本机防火墙的入站或出站策略与访问方向一致。
- 安全组规则的方向、源地址、目标端口和关联实例正确。
- NAT或端口映射的前后端地址和端口一致。
- 通过重复观察或抓包确认结果,而不是只依据一次瞬时输出。
- 记录命令执行时间、主机名、PID、监听地址、远端地址和异常状态,并对公网 IP、命令行中的密码或业务数据进行脱敏。
修改后的回滚要求
端口排查应优先采用只读命令。确需修改应用绑定、防火墙或安全组时,先保存当前配置和验收现场,再进行单项变更。
- 修改应用监听地址或端口前,备份配置文件,确认变更影响的服务和监听端口;优先使用应用支持的 reload,若必须 restart,要预留业务中断窗口。
- 修改主机防火墙前,导出当前规则,保留远程登录所需的管理端口;不要清空全部规则。
- 添加临时放行规则时,限制源地址、目标端口和有效时间,并记录规则编号或 nftables 句柄。
- 验证失败时,先删除临时规则或恢复变更前的配置,再重新执行
ss、lsof和连通性检查。 - 只有确认新监听已正常工作、旧端口不再使用且回滚路径可用后,才清理旧配置。
上线或验收检查清单
- [ ] 已确认正确的服务 PID、用户和启动参数。
- [ ] 已用
ss按 PID 查看 TCP/UDP套接字。 - [ ] 已用
lsof确认网络文件描述符、协议和远端端点。 - [ ] 已记录连接状态:
ESTAB、SYN-SENT、LISTEN或其他状态。 - [ ] 已确认远端域名解析结果、目标 IP和目标端口。
- [ ] 已用
ip route get核对出口接口和源地址。 - [ ] 已确认服务监听地址不是错误的
127.0.0.1或失效地址。 - [ ] 已检查本机防火墙对应方向的规则和默认策略。
- [ ] 已检查云安全组入站或出站规则。
- [ ] 已核对NAT、端口映射或负载均衡前后端端口。
- [ ] 必要时已通过抓包确认
SYN、SYN-ACK和应用数据的实际路径。 - [ ] 已保存带时间戳的命令输出和日志,并完成敏感信息脱敏。
- [ ] 如做过规则或配置调整,已验证回滚方法可执行。