linux 名額監控小記
自開始負責生産環境部署,中間遇到了若幹線上環境記憶體以及CPU的問題。由于微服務以及容器的流行,現在已經可以很友善的使用
K8s
+
prometheus
grafana
alert
的方式進行監控,這足以覆寫大部分場景。
最重要的事情已經交由最适合的元件去做,然而了解一些在裸機上的指令以及名額也是必不可少的:
- 了解監控什麼名額
- 平時寫一些腳本也經常會 OOM 或者 CPU 使用率過高
先以一張來自
linuxperf的圖作為大綱,我試着對一些名額進行整理,以備不時之需。

- 原文位址: linux 各項名額監控小記 · github
- 系列文章: 伺服器運維筆記
htop/top
htop 足以覆寫大多數名額,詳細直接檢視幫助即可。
這裡的 TIME 指的是 CPU 時間
htop 裡的 task 數指的是程序樹,top 裡的 task 數指的是程序樹 + 核心線程數,參考文章
https://www.cnblogs.com/arnoldlu/p/8336998.html
- sort: by mem/cpu/state. 根據程序狀态排序也至關重要,特别在 load average 過高的時候。根據記憶體以及CPU使用率排序用以定位高資源占用者。
- filter
- fields
- process/ count
- ...
CPU 基本資訊
在 linux 中一切皆檔案,檢視
/proc/cpuinfo
檢視資訊。另有衍生問題
- 如何檢視 CPU 個數
- 如何檢視 CPU model
- 如何檢視 CPU 主頻
cat /proc/cpuinfo
cat /proc/stat
平均負載 (load average)
使用
uptime
和
w
可列印出系統過去 1, 5, 15 分鐘内的平均負載。同時,你可以使用
sar -q
檢視動态的平均負載。
$ uptime
19:28:49 up 290 days, 20:25, 1 user, load average: 2.39, 2.64, 1.55
$ w
19:29:50 up 290 days, 20:26, 1 user, load average: 2.58, 2.63, 1.61
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 172.16.0.1 19:27 6.00s 0.05s 0.00s tmux a
在
uptime
的 man 手冊中這麼解釋平均負載
System load averages is the average number of processes that are either in a runnable or uninterruptable state.
翻譯過來就是指系統中處于可運作狀态和不可中斷狀态的平均程序數。
對于 4 核的 CPU,如果平均負載高于 4 就代表負載過高
動态平均負載
$ sar -q 1 100
Linux 3.10.0-957.21.3.el7.x86_64 (shanyue) 10/21/19 _x86_64_ (2 CPU)
16:55:52 runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked
16:55:53 0 464 0.07 0.11 0.13 0
16:55:54 0 464 0.06 0.10 0.13 0
16:55:55 0 464 0.06 0.10 0.13 0
16:55:56 0 464 0.06 0.10 0.13 0
16:55:57 0 464 0.06 0.10 0.13 0
16:55:57 0 464 0.06 0.10 0.13 0
Average: 0 464 0.06 0.10 0.13 0
CPU 使用率
可以直接使用
htop/top
指令檢視 CPU 使用率,
idle
的cpu時間也可以直接通過
top
顯示出來
CPU 使用率 = 1 - cpu-idle-time / cpu-time
$ top
%Cpu(s): 7.4 us, 2.3 sy, 0.0 ni, 90.1 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
- user: 使用者态,但不包括 nice
- system: 核心态
- nice: 低優先級使用者态,nice 值為 1-19 的 CPU 時間
- idle (id)
- iowait (wa)
- irq (hi)
- softirq (si)
- steal (st)
系統調用
strace
檢視系統調用
-
指定pid-p
-
統計各項系統調用被調用了多少次以及CPU時間-c
# 用來看一個程序所用到的系統調用
# -p: 指定 7477 号程序
$ strace -p 7477
# 用來檢視某指令需要用到的系統調用
$ strace cat index.js
# 關于系統調用的統計資訊
$ strace -p 7477 -c
記憶體
free
用以檢視系統記憶體。
如果檢視程序記憶體,使用
pidstat -r
或者
htop
$ free -h
total used free shared buff/cache available
Mem: 3.7G 682M 398M 2.1M 2.6G 2.7G
Swap: 0B 0B 0B
程序
衍生問題
- 如何根據指令名找到程序
- 如何根據參數名找到程序
- 程序狀态有哪些
- 如何擷取程序狀态
- 如何擷取程序的CPU占用率
- 如何擷取程序的記憶體占用
# 檢視 122 PID 程序
$ ps 122
# 根據指令名(command)找到 PID
$ pgrep -a node
26464 node /code/node_modules/.bin/ts-node index.ts
30549 node server.js
# 根據指令名以及參數找到 PID
$ pgrep -af ts-node
26464 node /code/node_modules/.bin/ts-node index.ts
# 檢視 122 PID 程序的資訊
$ cat /proc/122/status
$ cat /proc/122/*
# 列印父程序樹
# -s --show-parents: 顯示父程序
# -a --arguments: 顯示參數,如 echo hello 中 hello 為參數
$ pstree 122 -sap
procfs
http://man7.org/linux/man-pages/man5/proc.5.html程序的狀态
- D uninterruptible sleep (usually IO)
- R running or runnable (on run queue)
- S interruptible sleep (waiting for an event to complete)
- T stopped by job control signal
- t stopped by debugger during the tracing
- W paging (not valid since the 2.6.xx kernel)
- X dead (should never be seen)
- Z defunct ("zombie") process, terminated but not reaped by its parent
htop/top
可以檢視所有程序的狀态資訊,特别在幾種情況下常用
- 檢視過多的僵屍程序
- 當平均負載過大時
# 第二行可以統計所有程序的狀态資訊
$ top
...
Tasks: 214 total, 1 running, 210 sleeping, 0 stopped, 3 zombie
...
程序記憶體
ps -O rss
指定 rss 可以檢視程序的記憶體,另外還有指令
top/htop
與
pidstat -r
# 檢視 2579 PID 的記憶體
# -O rss 代表附加 RSS 資訊進行列印
$ ps -O rss 2579
PID RSS S TTY TIME COMMAND
2579 19876 S pts/10 00:00:03 node index.js
實時檢視程序記憶體
pidstat -sr
# 檢視 23097 PID 的記憶體資訊,每隔一秒列印一次
# -r: 檢視程序的記憶體資訊
# -s: 檢視程序的 stack 資訊
# -p: 指定 PID
# 1: 每間隔 1s 列印一次
# 5: 共列印 5 組
$ pidstat -sr -p 23097 1 5
Linux 3.10.0-693.2.2.el7.x86_64 (shanyue) 07/18/19 _x86_64_ (2 CPU)
18:56:07 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:08 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
18:56:08 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:09 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
18:56:09 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:10 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
18:56:10 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:11 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
18:56:11 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:12 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
Average: UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
Average: 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
頁表與缺頁異常
pidstat -s
中
minflt
majflt
代表缺頁異常
$ pidstat -s -p 23097 1 5
Linux 3.10.0-693.2.2.el7.x86_64 (shanyue) 07/18/19 _x86_64_ (2 CPU)
18:56:07 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:08 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
18:56:08 UID PID minflt/s majflt/s VSZ RSS %MEM StkSize StkRef Command
18:56:09 0 23097 0.00 0.00 366424 95996 2.47 136 80 node
标準輸出定位到檔案中
列出打開的檔案
lsof
, list open files
# 列出打開的檔案
$ lsof
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root cwd DIR 253,1 4096 2 /
systemd 1 root rtd DIR 253,1 4096 2 /
容器中 namespace PID -> global PID 映射
換一個問題就是,如何找出 docker 容器中的 pid 在主控端對應的 pid
# 容器環境
# 已知容器中該程序 PID 為 122
# 在容器中找到對應 PID 的資訊,在 /proc/$pid/sched 中包含主控端的資訊
$ cat /proc/122/sched
node (7477, #threads: 7)
...
# 主控端環境
# 7477 就是對應的 global PID,在主控端中可以找到
# -p 代表指定 PID
# -f 代表列印更多資訊
$ ps -fp 7477
UID PID PPID C STIME TTY TIME CMD
root 7477 7161 0 Jul10 ? 00:00:38 node index.js
global PID -> namespace PID 映射
換一個問題就是, 已知主控端的 PID,如何找出對應的容器
常見的場景就是使用
top/htop
定位到占用記憶體/CPU過高的程序,此時需要定位到它所在的容器
# 通過 docker inspect 查找到對應容器
$ docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.ID}}' | grep 22932
# 通過 cgroupfs 找到對應容器
$ cat /etc/22932/cgroup
幸運地是有人已經在 stackoverflow 上總結出來了
SWAP
# 查找關于
$ vmstat -s
inode
# -i: 列印 inode number
$ ls -lahi
網絡吞吐量
- 帶寬: 指網絡鍊路的最大傳輸速率
- 吞吐量: 代表機關時間内成功傳輸的資料量,機關為 b/s (KB/s, MB/s)
- PPS: pck/s (Packet Per Second),以網絡包為機關的傳輸速率
# 檢視網卡資訊
$ ifconfig eth0
$ sar -n DEV 1 | grep eth0
# IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
16:34:37 eth0 8.00 2.00 0.69 1.90 0.00 0.00 0.00
16:34:38 eth0 39.00 27.00 2.91 38.11 0.00 0.00 0.00
16:34:39 eth0 13.00 11.00 0.92 13.97 0.00 0.00 0.00
16:34:40 eth0 16.00 16.00 1.21 20.86 0.00 0.00 0.00
16:34:41 eth0 17.00 17.00 1.51 15.27 0.00 0.00 0.00
Average: eth0 18.60 14.60 1.45 18.02 0.00 0.00 0.00
socket 狀态
socket 資訊
推薦使用
ss
,不過
netstat
仍需要掌握,在特定條件 (docker 中) 有可能沒有
ss
指令。
# -t TCP
# -a 所有狀态
# -n 顯示數字位址和端口号
# -p 顯示 pid
$ netstat -tanp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.11:35283 0.0.0.0:* LISTEN -
tcp 0 0 192.168.112.2:37344 172.18.0.1:6379 ESTABLISHED 78/node
tcp 0 0 :::80 :::* LISTEN 78/node
-
Recv-Q
不為0時,表示網絡包堆積,需要注意Send-Q
協定資訊
# 展示對每個協定的統計資訊
$ netstat -s
# 展示對每個協定的統計資訊
$ ss -s
Total: 1468 (kernel 1480)
TCP: 613 (estab 270, closed 315, orphaned 0, synrecv 0, timewait 41/0), ports 0
Transport Total IP IPv6
* 1480 - -
RAW 0 0 0
UDP 30 22 8
TCP 298 145 153
INET 328 167 161
FRAG 0 0 0
# 也可以這樣統計 estab socket 的數量
$ netstat -tanp | grep ESTAB | wc -l
TCP 連接配接數
PostgresSQL 的最大連接配接數與目前連接配接數
-- 最大連接配接數
show max_connections;
-- 目前連接配接數
select count(*) from pg_stat_activity;
mysql 的最大連接配接數與目前連接配接數
-- 最大連接配接數
show variables like 'max_connections';
-- 目前連接配接數
show full processlist;