Contents

Linux 查詢執行很久程式方法

在 Linux 系統上,有時需要找出執行時間過長或佔用資源過多的程序,例如排查效能瓶頸、清理僵屍程序,或是終止卡住的任務。以下整理幾種常用方法。

使用 ps 查看程序執行時間

查看所有程序並依 CPU 排序

1
ps aux --sort=-%cpu | head -20

欄位說明:

  • USER:程序擁有者
  • PID:程序 ID
  • %CPU:CPU 使用率
  • %MEM:記憶體使用率
  • ELAPSED / TIME:累積 CPU 時間

查看程序的實際執行時間(elapsed time)

1
ps -eo pid,etime,cmd --sort=-etime | head -20
  • etime:程序從啟動到現在的經過時間,格式為 [[dd-]hh:]mm:ss
  • --sort=-etime:依執行時間降冪排序(最久的在最前面)

例如找出執行超過 1 小時的程序:

1
2
3
4
5
6
7
ps -eo pid,etime,cmd | awk '{
    split($2, t, "[-:]")
    if (length(t) == 4) hours = t[2]
    else if (length(t) == 3) hours = t[1]
    else hours = 0
    if (hours+0 >= 1) print $0
}'

使用 top / htop 即時監控

top

1
top

常用互動快捷鍵:

  • P:依 CPU 排序
  • M:依記憶體排序
  • k:輸入 PID 終止程序
  • q:離開

htop(需另外安裝)

1
2
sudo apt install htop  # Debian/Ubuntu
htop

htop 提供更友善的彩色介面,可用方向鍵選擇程序,F9 送訊號,F10 離開。

透過 /proc 目錄查詢

Linux 的 /proc 目錄包含所有程序的即時資訊。/proc/<pid>/stat 中記錄了程序的啟動時間(以系統開機後的時鐘滴答數計算)。

1
2
# 查看 PID 1234 的啟動時間(滴答數)
cat /proc/1234/stat | awk '{print $22}'

搭配 getconf CLK_TCK(通常為 100)和 /proc/uptime 可計算出實際執行時間:

1
2
3
4
5
6
7
pid=1234
clk_tck=$(getconf CLK_TCK)
uptime_sec=$(awk '{print int($1)}' /proc/uptime)
start_ticks=$(awk '{print $22}' /proc/$pid/stat)
start_sec=$((start_ticks / clk_tck))
elapsed=$((uptime_sec - start_sec))
echo "程序 $pid 已執行 $elapsed 秒"

找出執行超過 N 分鐘的程序

結合 find/proc,找出所有數字命名的目錄(即程序目錄):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
find /proc -maxdepth 1 -type d -name '[0-9]*' | while read dir; do
    pid=$(basename $dir)
    if [ -f "$dir/stat" ]; then
        start_ticks=$(awk '{print $22}' "$dir/stat" 2>/dev/null)
        clk_tck=$(getconf CLK_TCK)
        uptime_sec=$(awk '{print int($1)}' /proc/uptime)
        elapsed=$(( uptime_sec - start_ticks / clk_tck ))
        if [ "$elapsed" -gt 300 ]; then  # 超過 300 秒(5 分鐘)
            cmd=$(cat "$dir/cmdline" 2>/dev/null | tr '\0' ' ')
            echo "PID=$pid elapsed=${elapsed}s cmd=$cmd"
        fi
    fi
done

參考資料