Socket 状态变迁图及命令行查看方法

Socket 状态变迁图

命令行查看方法

查看 socket 信息可以帮我们回答下列问题:

  1. 我的程序是不是真的在监听我指定的端口?
  2. 我的程序是在监听 127.0.0.1(本机),还是在监听 0.0.0.0(整个网络)
  3. 进程们分别在使用哪些端口?
  4. 我的连接数是否达到了上限?

我们使用 ss (socket statistics)命令来查看 socket 信息(CentOS/Ubuntu 已经使用 ss 替换了 netstat,推荐使用 ss):

# 查看 socket 连接的统计信息
# 主要统计处于各种状态的 tcp sockets 数量,以及其他 sockets 的统计信息
ss --summary
ss -s  # 缩写

# 查看那个进程在监听 80 端口
# --listening 列出所有正在被监听的 socket
# --processes 显示出每个 socket 对应的 process 名称和 pid
ss --listening --processes | grep 80
ss -lp | grep 80  # 缩写
## 使用过时的 netstat
### -t tcp
### -u udp
netstat -tunlp | grep ":80"

# 查看 sshd 当前使用的端口号
ss --listening --processes | grep sshd
## 使用过时的 netstat
netstat -tunlp | grep <pid>  # pid 通过 ps 命令获得

# 列出所有的 tcp sockets,包括所有的 socket 状态
ss --tcp --all

# 只列出正在 listen 的 socket
ss --listening

# 列出所有 ESTABLISHED 的 socket(默认行为)
ss

# 列出所有 ESTABLISHED 的 socket,并且给出连接的计时器
ss --options

# 查看所有来自 192.168.5 的 sockets
ss dst 192.168.1.5

# 查看本机与服务器 192.168.1.100 建立的 sockets
ss src 192.168.1.5

# 查看路由表
route

TCP 连接数受 Linux 文件描述符上限控制,可以通过如下方法查看已用文件句柄的数量。

# 已用文件描述符数量
lsof | wc -l
# 文件描述符上限
ulimit -n 

查看 Docker 容器的 socket 信息

Docker 容器有自己的 namespace,直接通过宿主机的 ss 命令是查看不到容器的 socket 信息的。

比较直观的方法是直接通过 docker exec 在容器中通过 ss 命令。但是这要求容器中必须自带 ss 等程序,有的精简镜像可能不会自带它。

因此用的更多的方法,有两种:

1. 通过 nsenter 直接在目标容器的 namespace 中使用宿主机的命令。

这个适合单机 docker 的网络诊断,用法如下:

# 1. 查询到容器对应的 pid
PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)

# 2. nsenter 通过 pid 进入容器的 network namespace,执行 ss 查看 socket 信息
nsenter --target $PID --net ss -s

nsenter 这个工具貌似是 docker 自带的,只要装了 docker,ubuntu/centos 都可以直接使用这个命令。

2. 使用专用的网络诊断镜像进行容器网络诊断(SideCar)

这种方式一般用于容器集群的诊断,K8s 社区提供了一个工具 kubectl-debug,以这种 SideCar 的方式进行容器诊断。详情参见它的文档。

Windows 系统查看 socket 信息

Windows 系统没有 ss,但是自带 netstat,该命令和 Linux 下的 netstat 有一定差别,具体使用方法如下:

netstat -?  # 查看使用帮助,很清晰易懂

# 查看那个进程在监听 80 端口,最后一列是进程的 Pid
netstat -ano | findstr 80        # windows 命令
netstat -ano | select-string 80  # powershell 命令

# 不仅列出 Pid,还给出 Pid 对应的可执行文件名称(需要管理员权限)
netstat -ano -b | select-string 80  # powershell 命令

# 列出所有 ESTABLISHED 的 socket(默认行为)
netstat

# 列出所有正在监听的端口
netstat -ano | findstr LISTENING

# 只列出 TCP 连接
netstat -ano -p TCP


# 查看路由表
route -?  # 查看使用帮助,很清晰易懂
route print    # 查看所有路由信息
route print -4  # 仅 ipv4

比如我们遇到端口占用问题时,就可以通过上述命令查找到端口对应的 Pid,然后使用 kill <Pid> 命令(powershell stop-process 的别名)杀死对应的进程。

参考

posted @ 2020-02-02 13:29  於清樂  阅读(...)  评论(...编辑  收藏