Socket 狀態變遷圖
命令行查看方法
查看 socket 信息可以幫我們回答下列問題:
- 我的程序是不是真的在監聽我指定的端口?
- 我的程序是在監聽 127.0.0.1(本機),還是在監聽 0.0.0.0(整個網絡)
- 進程們分別在使用哪些端口?
- 我的連接數是否達到了上限?
我們使用 ss (socket statistics)命令來查看 socket 信息(CentOS/Ubuntu 已經使用 ss
替換了 netstat
,推薦使用 ss):
# 查看 socket 連接的統計信息
# 主要統計處於各種狀態的 tcp sockets 數量,以及其他 sockets 的統計信息
ss --summary
ss -s # 縮寫
# 查看哪個進程在監聽 80 端口
# --listening 列出所有正在被監聽的 socket
# --processes 顯示出每個 socket 對應的 process 名稱和 pid
# --numeric 直接打印數字端口號(不解析協議名稱)
ss --listening --processes --numeric | grep 80
ss -nlp | grep 80 # 縮寫
ss -lp | grep http # 解析協議名稱,然后通過協議名搜索監聽
## 使用過時的 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
# 統計 TCP 連接數
ss | grep ESTAB | wc -l
# 列出所有 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
# 查看路由表
routel
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
的別名)殺死對應的進程。