目前整個流程是:
server01
↓
Prometheus
↓
Grafana
↓
Alert Rule
↓
Discord
當 CPU 持續超過設定的門檻時,我們已經可以收到:
[FIRING]
Server01 High CPU
但收到通知之後,真正的維運工作才剛開始。
因為接下來通常還是要登入 Server,確認:
CPU 現在多少?
Memory 有沒有一起升高?
Disk 是否正常?
哪個 Process 正在吃 CPU?
所以今天想先解決這件事情。
既然這些資訊每次都要查,那能不能讓 Python 先幫我收集?
今天要做到什麼?
先不接 AI,也先不修改 Grafana。
今天只完成這個流程:
server01
↓
Python
↓
收集系統資訊
↓
CPU
Memory
Disk
Process
↓
輸出故障資訊
等這支程式可以正常工作之後,後面再想辦法讓 Grafana 告警自動觸發它。
Step 1:準備 Python 環境
先登入 server01:
確認 Python:
python3 --version
接著準備虛擬環境:
sudo apt update
sudo apt install python3-venv -y
建立專案:
mkdir ~/aiops
cd ~/aiops
建立 Python Virtual Environment:
python3 -m venv venv
啟用:
source venv/bin/activate
接著安裝今天會使用的套件:
pip install psutil
psutil 可以讓 Python 取得系統的 CPU、Memory、Disk 和 Process 資訊。
Step 2:先取得基本主機資訊
建立:
nano collect_info.py
先從最基本的資訊開始:
import socket
import psutil
from datetime import datetime
hostname = socket.gethostname()
cpu = psutil.cpu_percent(interval=1)
memory = psutil.virtual_memory()
disk = psutil.disk_usage("/")
print("=== System Information ===")
print(f"Time: {datetime.now()}")
print(f"Hostname: {hostname}")
print(f"CPU Usage: {cpu}%")
print(f"Memory Usage: {memory.percent}%")
print(f"Disk Usage: {disk.percent}%")
執行:
python collect_info.py
應該會看到類似:
=== System Information ===
Time: 2026-09-04 09:30:20
Hostname: server01
CPU Usage: 32.5%
Memory Usage: 48.2%
Disk Usage: 36.1%
到這裡,我們已經不用分別輸入好幾個 Linux 指令。
Python 已經可以一次把基本資訊整理出來。
Step 3:找出 CPU 使用率較高的 Process
如果今天收到的是:
High CPU
只知道 CPU 95% 還是不夠。
下一個問題一定是:
到底是哪個 Process 在使用 CPU?
所以繼續修改程式。
import socket
import time
import psutil
from datetime import datetime
hostname = socket.gethostname()
cpu = psutil.cpu_percent(interval=1)
memory = psutil.virtual_memory()
disk = psutil.disk_usage("/")
processes = []
for process in psutil.process_iter(["pid", "name"]):
try:
process.cpu_percent(None)
processes.append(process)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
time.sleep(1)
process_list = []
for process in processes:
try:
process_list.append({
"pid": process.pid,
"name": process.name(),
"cpu": process.cpu_percent(None),
"memory": round(process.memory_percent(), 2)
})
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
process_list = sorted(
process_list,
key=lambda x: x["cpu"],
reverse=True
)[:5]
print("=== System Information ===")
print(f"Time: {datetime.now()}")
print(f"Hostname: {hostname}")
print(f"CPU Usage: {cpu}%")
print(f"Memory Usage: {memory.percent}%")
print(f"Disk Usage: {disk.percent}%")
print("\n=== Top CPU Processes ===")
for process in process_list:
print(
f'PID: {process["pid"]} '
f'Name: {process["name"]} '
f'CPU: {process["cpu"]}% '
f'Memory: {process["memory"]}%'
)
再次執行:
python collect_info.py
這次除了系統資訊之外,還會看到:
=== Top CPU Processes ===
PID: 1352 Name: python3 CPU: 42.0% Memory: 3.2%
PID: 921 Name: nginx CPU: 15.3% Memory: 1.5%
PID: 754 Name: sshd CPU: 2.1% Memory: 0.8%
這就開始比較像真正排查問題時需要的資訊了。
Step 4:把結果留下來
如果只顯示在 Terminal,程式結束之後就不太方便後續處理。
所以我希望順便把資料存成 JSON。
加入:
import json
接著整理資料:
report = {
"time": datetime.now().isoformat(),
"hostname": hostname,
"cpu": cpu,
"memory": memory.percent,
"disk": disk.percent,
"top_processes": process_list
}
最後寫入檔案:
with open("incident.json", "w") as file:
json.dump(report, file, indent=4)
執行:
python collect_info.py
目錄裡就會多出:
incident.json
打開:
cat incident.json
可能會看到:
{
"time": "2026-09-04T09:35:12",
"hostname": "server01",
"cpu": 92.4,
"memory": 58.3,
"disk": 36.1,
"top_processes": [
{
"pid": 1352,
"name": "python3",
"cpu": 45.2,
"memory": 3.2
}
]
}
這個 JSON 其實很重要。
因為後面不論是:
存進 Database
↓
送給 API
↓
傳給 AI
都可以直接使用這份資料。
為什麼先整理成 JSON?
如果只是讓 AI 直接去看整台 Server,我覺得範圍太大。
我比較希望流程是:
Server
↓
Python 收集資料
↓
整理成固定格式
↓
再交給下一個系統
這樣後面的程式不用自己猜:
哪一行是 CPU?
哪一行是 Memory?
而是直接取得:
{
"cpu": 92.4,
"memory": 58.3,
"disk": 36.1
}
資料會比較容易處理。
現在和以前有什麼不同?
原本收到 High CPU Alert 之後,可能要自己輸入:
top
再查:
free -h
再看:
df -h
然後自己把資訊拼起來。
現在變成:
python collect_info.py
一次得到:
Hostname
CPU
Memory
Disk
Top CPU Processes
目前看起來只少打幾個指令。
但這一步的真正目的,是為後面的:
自動觸發
做準備。
Day 8 完成
今天我們第一次加入自己寫的程式。
目前完成:
✓ 建立 Python 環境
✓ 使用 psutil 取得系統資訊
✓ 收集 CPU
✓ 收集 Memory
✓ 收集 Disk
✓ 找出高 CPU Process
✓ 將結果儲存成 JSON
目前架構也開始多出自己的程式:
server01
│
├── Node Exporter
│ ↓
│ Prometheus
│ ↓
│ Grafana
│
└── Python Collector
↓
incident.json
但現在還有一個很明顯的問題。
這支程式目前還需要自己手動執行:
python collect_info.py
這跟我們要做的「自動化維運」還差一步。