Linux進(jìn)程排查實(shí)戰(zhàn)之strace和lsof命令使用指南
服務(wù)起不來,日志沒報(bào)錯(cuò)。進(jìn)程在跑,但就是不干活。
這種問題最惡心,看日志看不出問題,看監(jiān)控也沒異常。
這時(shí)候就需要strace和lsof這兩個(gè)神器了。
strace:跟蹤系統(tǒng)調(diào)用
strace能看到進(jìn)程在做什么系統(tǒng)調(diào)用,相當(dāng)于給進(jìn)程裝了個(gè)監(jiān)控?cái)z像頭。
基本用法
# 跟蹤一個(gè)命令 strace ls # 跟蹤正在運(yùn)行的進(jìn)程 strace -p <pid> # 跟蹤子進(jìn)程 strace -f -p <pid>
案例一:服務(wù)啟動(dòng)卡住
現(xiàn)象:Java服務(wù)啟動(dòng)后卡住,不打印任何日志。
# 找到進(jìn)程號(hào) ps aux | grep java # 假設(shè)是12345 # strace跟蹤 strace -p 12345
輸出:
futex(0x7f8a8c000000, FUTEX_WAIT_PRIVATE, 0, NULL
卡在futex,說明在等鎖。
進(jìn)一步看是什么鎖:
strace -p 12345 -e trace=futex -T
結(jié)合jstack看線程棧:
jstack 12345 > thread.dump grep -A 20 "BLOCKED" thread.dump
發(fā)現(xiàn)是啟動(dòng)時(shí)連接數(shù)據(jù)庫,數(shù)據(jù)庫連不上,超時(shí)時(shí)間設(shè)太長(zhǎng)了。
案例二:文件讀寫問題
現(xiàn)象:服務(wù)很慢,但CPU和內(nèi)存都不高。
# 只看文件相關(guān)的調(diào)用 strace -p 12345 -e trace=file # 或者看所有IO strace -p 12345 -e trace=read,write,open,close
輸出:
open("/data/logs/app.log", O_WRONLY|O_APPEND) = 3
write(3, "2024-12-23 10:00:00 INFO...", 1024) = 1024
close(3) = 0
open("/data/logs/app.log", O_WRONLY|O_APPEND) = 3
write(3, "2024-12-23 10:00:00 INFO...", 1024) = 1024
close(3) = 0
...
每次寫日志都o(jì)pen-write-close,頻繁的文件操作導(dǎo)致性能差。
改成保持文件句柄打開,或者用異步日志。
案例三:網(wǎng)絡(luò)問題
現(xiàn)象:服務(wù)偶爾超時(shí)。
# 只看網(wǎng)絡(luò)相關(guān) strace -p 12345 -e trace=network -T
輸出:
connect(5, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("10.0.0.1")}, 16) = -1 ETIMEDOUT (Connection timed out) <30.001234>
連接數(shù)據(jù)庫超時(shí)30秒,問題找到了。
常用參數(shù)
# -f:跟蹤子進(jìn)程 strace -f -p 12345 # -T:顯示每個(gè)調(diào)用耗時(shí) strace -T -p 12345 # -t:顯示時(shí)間戳 strace -t -p 12345 # -c:統(tǒng)計(jì)系統(tǒng)調(diào)用次數(shù)和耗時(shí) strace -c -p 12345 # -o:輸出到文件 strace -o trace.log -p 12345 # 組合使用 strace -f -T -t -o trace.log -p 12345
統(tǒng)計(jì)分析
strace -c -p 12345
輸出:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.23 2.345678 234 10000 write
30.12 1.234567 1234 1000 read
20.11 0.987654 98 10000 futex
4.54 0.234567 23 10000 clock_gettime
------ ----------- ----------- --------- --------- ----------------
100.00 4.802466 31000 total
一眼就能看出時(shí)間花在哪了。
lsof:列出打開的文件
Linux里一切皆文件,lsof能看到進(jìn)程打開了什么文件、網(wǎng)絡(luò)連接、設(shè)備等。
基本用法
# 查看進(jìn)程打開的所有文件 lsof -p <pid> # 查看某個(gè)文件被誰打開 lsof /var/log/app.log # 查看某個(gè)端口 lsof -i :8080 # 查看某個(gè)用戶的所有打開文件 lsof -u root
案例一:端口被占用
# 誰占用了8080端口 lsof -i :8080
輸出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 12345 root 123u IPv6 123456 0t0 TCP *:8080 (LISTEN)
進(jìn)程12345占用了8080端口。
案例二:文件句柄泄漏
現(xiàn)象:服務(wù)運(yùn)行一段時(shí)間后報(bào)"Too many open files"。
# 查看進(jìn)程打開的文件數(shù)
lsof -p 12345 | wc -l
# 按文件類型分組統(tǒng)計(jì)
lsof -p 12345 | awk '{print $5}' | sort | uniq -c | sort -rn
輸出:
5000 IPv4
3000 REG
1000 DIR
5000個(gè)網(wǎng)絡(luò)連接?明顯有連接泄漏。
# 看看都連了誰 lsof -p 12345 -i | head -20
輸出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 12345 root 123u IPv4 123456 0t0 TCP 10.0.0.1:54321->10.0.0.2:3306 (ESTABLISHED)
java 12345 root 124u IPv4 123457 0t0 TCP 10.0.0.1:54322->10.0.0.2:3306 (ESTABLISHED)
java 12345 root 125u IPv4 123458 0t0 TCP 10.0.0.1:54323->10.0.0.2:3306 (ESTABLISHED)
...
全是連數(shù)據(jù)庫的,連接池用完沒歸還。
案例三:刪除的文件還在占用空間
# 查看已刪除但仍被引用的文件 lsof +L1
輸出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
java 12345 root 10w REG 253,1 10737418240 0 12345 /var/log/app.log (deleted)
日志文件被刪了,但進(jìn)程還引用著,10G空間釋放不掉。
解決:重啟服務(wù),或者truncate文件:
# 找到文件描述符路徑 ls -l /proc/12345/fd/10 # 清空內(nèi)容但不關(guān)閉句柄 : > /proc/12345/fd/10
案例四:網(wǎng)絡(luò)連接分析
# 查看所有網(wǎng)絡(luò)連接
lsof -i
# 只看TCP
lsof -i tcp
# 只看某個(gè)狀態(tài)
lsof -i | grep ESTABLISHED
# 統(tǒng)計(jì)連接數(shù)
lsof -i | grep ESTABLISHED | wc -l
# 按目標(biāo)地址分組
lsof -i | grep ESTABLISHED | awk '{print $9}' | cut -d'>' -f2 | cut -d':' -f1 | sort | uniq -c | sort -rn
組合使用
排查思路
- 先用top/htop看整體
- 用ps看進(jìn)程狀態(tài)
- 用lsof看打開了什么
- 用strace看在做什么
實(shí)戰(zhàn):服務(wù)假死排查
現(xiàn)象:服務(wù)進(jìn)程在,但不響應(yīng)請(qǐng)求。
# 1. 看進(jìn)程狀態(tài)
ps aux | grep java
# 狀態(tài)是Sl,正常
# 2. 看打開的文件和連接
lsof -p 12345 | wc -l
# 8000+,有點(diǎn)多
# 3. 看網(wǎng)絡(luò)連接
lsof -p 12345 -i | grep -c ESTABLISHED
# 5000+,太多了
# 4. 看連接狀態(tài)分布
ss -tnp | grep 12345 | awk '{print $4}' | sort | uniq -c
# 大量CLOSE_WAIT
# 5. strace看在做什么
strace -p 12345 -e trace=network
# 卡在accept上,但新連接進(jìn)不來
根因:連接池滿了,CLOSE_WAIT狀態(tài)的連接沒有正確關(guān)閉。
實(shí)戰(zhàn):CPU 100%排查
# 1. top找到占用CPU的進(jìn)程 top -c # PID 12345 CPU 99% # 2. 看線程CPU使用 top -H -p 12345 # TID 12346 CPU 99% # 3. 把線程ID轉(zhuǎn)成16進(jìn)制 printf "%x\n" 12346 # 303a # 4. jstack看線程棧(Java) jstack 12345 | grep -A 30 "0x303a" # 5. 或者用strace看系統(tǒng)調(diào)用 strace -p 12346 -c
遠(yuǎn)程排查
有時(shí)候問題機(jī)器在遠(yuǎn)程,需要登錄排查。
我們有幾臺(tái)服務(wù)器在不同機(jī)房,之前用跳板機(jī)一層層跳很麻煩。現(xiàn)在用星空組網(wǎng)把所有機(jī)器組到一起,直接SSH過去就能用strace、lsof排查,效率高多了。
常用命令速查
# strace速查 strace -p <pid> # 跟蹤進(jìn)程 strace -f -p <pid> # 跟蹤包括子進(jìn)程 strace -e trace=network -p <pid> # 只看網(wǎng)絡(luò) strace -e trace=file -p <pid> # 只看文件 strace -c -p <pid> # 統(tǒng)計(jì) strace -T -p <pid> # 顯示耗時(shí) # lsof速查 lsof -p <pid> # 進(jìn)程打開的文件 lsof -i :<port> # 誰占用端口 lsof -i tcp # 所有TCP連接 lsof +L1 # 已刪除但仍占用的文件 lsof -u <user> # 用戶打開的文件
總結(jié)
| 工具 | 用途 | 典型場(chǎng)景 |
|---|---|---|
| strace | 跟蹤系統(tǒng)調(diào)用 | 卡死、慢、報(bào)錯(cuò)看不出原因 |
| lsof | 看打開的文件/連接 | 端口占用、文件泄漏、連接泄漏 |
排查原則:
- 從宏觀到微觀
- 從現(xiàn)象到根因
- 不確定就多看幾遍
這兩個(gè)工具用熟了,大部分疑難雜癥都能查出來。
以上就是Linux進(jìn)程排查實(shí)戰(zhàn)之strace和lsof命令使用指南的詳細(xì)內(nèi)容,更多關(guān)于Linux strace和lsof命令的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
linux 網(wǎng)絡(luò)編程 socket選項(xiàng)的實(shí)現(xiàn)
這篇文章主要介紹了linux 網(wǎng)絡(luò)編程 socket選項(xiàng)的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-06-06
Linux進(jìn)程池實(shí)現(xiàn)的詳細(xì)指南
如果你了解過STL的底層設(shè)計(jì),你會(huì)發(fā)現(xiàn)在其中會(huì)有一個(gè)叫做內(nèi)存池的設(shè)計(jì),其作用就是先申請(qǐng)出一片空間,如果后續(xù)你需要對(duì)你的容器進(jìn)行擴(kuò)容,所擴(kuò)展的空間就從內(nèi)存池里取的,本文給大家介紹了Linux進(jìn)程池實(shí)現(xiàn)的詳細(xì)指南,需要的朋友可以參考下2024-11-11
淺談在linux kernel中打印函數(shù)調(diào)用的堆棧的方法
下面小編就為大家?guī)硪黄獪\談在linux kernel中打印函數(shù)調(diào)用的堆棧的方法。小編覺得挺不錯(cuò)的?,F(xiàn)在就分享給大家。也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12
詳解Ubuntu14.04橋接網(wǎng)絡(luò)設(shè)置與SSH登陸
本篇文章主要介紹了詳解Ubuntu14.04橋接網(wǎng)絡(luò)設(shè)置與SSH登陸,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01

