用 PM2 + Bun 管理 Python FastAPI 服務:從 systemd 遷移實戰
用 PM2 + Bun 管理 Python FastAPI 服務:從 systemd 遷移實戰
PM2 是 Node.js 生態系中最受歡迎的進程管理工具,但你知道嗎?它其實也能完美管理 Python、Go、Rust 等任何可執行程式。本文記錄了將一個 FastAPI search server 從 systemd 遷移到 PM2 的完整過程。
為什麼選擇 PM2?
相較於 systemd,PM2 提供了更友善的開發者體驗:
| 特性 | systemd | PM2 |
|---|---|---|
| 日誌查看 | journalctl -u service |
pm2 logs |
| 重啟服務 | systemctl restart service |
pm2 restart app |
| 查看狀態 | systemctl status service |
pm2 list |
| 設定檔 | 需要 root 權限編輯 /etc/systemd/system/ |
專案目錄下的 ecosystem.config.js |
| 即時監控 | 無內建 | pm2 monit |
| 叢集模式 | 需手動設定 | -i max 一行搞定 |
環境準備
使用 Bun 安裝 PM2
如果你已經有 Bun,可以直接用它來安裝 PM2:
bun install -g pm2
注意:PM2 的某些功能(如
pm2 startup)仍需要 Node.js。如果你只用 Bun,可能需要額外安裝 Node.js:sudo apt install nodejs
安裝完成後,如果 pm2 指令無法直接使用(因為 Bun 的 global bin 可能不在 PATH 中),可以建立一個 wrapper script:
mkdir -p ~/.local/bin
echo '#!/bin/bash
exec bun ~/.bun/install/global/node_modules/pm2/bin/pm2 "$@"' > ~/.local/bin/pm2
chmod +x ~/.local/bin/pm2
驗證安裝:
pm2 --version
# 6.0.14
設定 Python FastAPI 應用
建立 ecosystem.config.js
在專案根目錄建立 ecosystem.config.js:
module.exports = {
apps: [{
name: "search-server",
cwd: "./search", // 工作目錄
script: ".venv/bin/python", // 使用 venv 的 Python
args: "-m uvicorn server:app --host 0.0.0.0 --port 8000",
interpreter: "none", // 不使用 Node.js 解釋器
watch: false, // 不自動監控檔案變更
autorestart: true, // 自動重啟
max_restarts: 10, // 最大重啟次數
env: {
// 環境變數(可選,app 也可從 .env 讀取)
}
}]
}
關鍵設定說明:
interpreter: "none":告訴 PM2 這不是 Node.js 應用,直接執行script指定的程式cwd:設定工作目錄,讓相對路徑能正確解析script+args:使用 venv 的 Python 來執行 uvicorn
啟動服務
pm2 start ecosystem.config.js
輸出範例:
[PM2] App [search-server] launched (1 instances)
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ search-server │ fork │ 0 │ online │ 0% │ 205.8mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
處理 Port 衝突
如果舊的服務還在佔用 port,需要先停止它:
# 找出佔用 port 的進程
lsof -i :8000
# 停止舊進程
kill <PID>
# 重啟 PM2 管理的服務
pm2 restart search-server
設定開機自動啟動
PM2 可以整合 systemd 實現開機自動啟動:
# 產生 startup script(需要 Node.js)
pm2 startup
# 會輸出一行需要 sudo 執行的指令,複製執行它
sudo env PATH=$PATH:/home/user/.bun/bin ... pm2 startup systemd ...
# 儲存目前的進程列表
pm2 save
這會建立 /etc/systemd/system/pm2-<username>.service,開機時自動恢復所有 PM2 管理的進程。
PM2 日常操作指南
基本指令
| 指令 | 說明 |
|---|---|
pm2 list |
列出所有進程 |
pm2 start app |
啟動應用 |
pm2 stop app |
停止應用 |
pm2 restart app |
重啟應用 |
pm2 reload app |
零停機重載(適用於 cluster mode) |
pm2 delete app |
從 PM2 列表中刪除應用 |
監控與日誌
# 即時日誌
pm2 logs
# 只看特定應用的日誌
pm2 logs search-server
# 顯示最後 100 行
pm2 logs --lines 100
# 即時監控面板
pm2 monit
進階操作
# 重啟所有應用
pm2 restart all
# 停止所有應用
pm2 stop all
# 儲存目前進程列表(用於 startup 恢復)
pm2 save
# 查看詳細資訊
pm2 show search-server
# 重新載入設定檔
pm2 reload ecosystem.config.js
管理 PM2 本身
# 停止 PM2 daemon
pm2 kill
# 更新 PM2
bun update -g pm2
# 移除 startup script
pm2 unstartup systemd
實用技巧
1. 開發模式:自動重啟
// ecosystem.config.js
{
name: "search-server-dev",
watch: true,
watch_delay: 1000,
ignore_watch: ["node_modules", ".git", "__pycache__", ".venv"],
}
2. 環境變數管理
{
env: {
NODE_ENV: "development",
PORT: 8000
},
env_production: {
NODE_ENV: "production",
PORT: 80
}
}
// 啟動時指定環境
// pm2 start ecosystem.config.js --env production
3. 記憶體限制(自動重啟)
{
max_memory_restart: "500M"
}
4. 日誌檔案管理
{
error_file: "./logs/error.log",
out_file: "./logs/output.log",
log_date_format: "YYYY-MM-DD HH:mm:ss Z",
merge_logs: true
}
總結
PM2 提供了比 systemd 更友善的進程管理體驗,特別適合開發者日常使用。透過 Bun 安裝可以減少對 npm 的依賴,但某些進階功能(如 startup)仍需要 Node.js。
完整的專案結構範例:
project/
├── ecosystem.config.js # PM2 設定
├── search/
│ ├── .venv/ # Python 虛擬環境
│ ├── server.py # FastAPI 應用
│ └── pyproject.toml
└── .env # 環境變數
現在你可以用簡單的 pm2 restart search-server 來重啟服務,用 pm2 logs 來追蹤日誌,享受更流暢的開發體驗!