您用 aiogram 寫了一個 Telegram 機器人、在本機測過、它能用。現在它得住在一個您合上筆電時不會睡眠的地方。一台小 VPS 是天然的家——但從 SSH 工作階段裡的 python bot.py 到一個真正能熬過崩潰、重新啟動和您連線掉線的機器人,中間有一道坎。
這是生產版本:一個 virtualenv、token 放在程式碼之外、一個自己復活機器人的 systemd 服務,以及對每個人最終都會問的那個問題的清醒回答——輪詢還是 webhook?
為什麼不直接在筆電上跑
一個機器人需要一條到 Telegram 的穩定對外連線。您的筆電會睡眠、為更新重新啟動、在網路間跳——這裡每一樣都讓機器人掉線,使用者撞上一片沉默。一台 VPS 全天候保持那條連線。那就是把它從您機器上搬走的全部理由,也是一個 Discord 機器人也該待在伺服器上的同一個理由。
如果您只想要用一個極簡機器人最快「讓它上線」的路徑,託管 Telegram 機器人走查講了那個。本篇更深一層:aiogram、安全的 token 處理,以及知道何時該擴容。
機器人,裝在 virtualenv 裡
SSH 進去、把機器人隔離在它自己的 venv 裡——別全系統裝包,那會讓以後的升級和清理一團糟:
sudo apt update && sudo apt install -y python3-venv
mkdir ~/tgbot && cd ~/tgbot
python3 -m venv venv && source venv/bin/activate
pip install -U aiogram
一個從環境讀 token、而不是從硬編碼字串讀的極簡 aiogram 3 機器人:
# bot.py
import asyncio, logging, os
from aiogram import Bot, Dispatcher
from aiogram.types import Message
from aiogram.filters import CommandStart
logging.basicConfig(level=logging.INFO)
dp = Dispatcher()
@dp.message(CommandStart())
async def start(m: Message):
await m.answer("Alive and running on a VPS.")
async def main():
bot = Bot(os.environ["BOT_TOKEN"])
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
把 token 放在程式碼之外
永遠別把 BotFather 的 token 粘進 bot.py——往公開儲存庫一推它就洩露了。改把它放在一個 root 可讀的環境檔案裡:
sudo tee /etc/tgbot.env >/dev/null <<'EOF'
BOT_TOKEN=123456:your-token-from-botfather
EOF
sudo chmod 600 /etc/tgbot.env
一個洩露的 token,在 BotFather 裡一個 /revoke 就修好了——但一台共享機器上洩露別的任何東西更糟。一台給機器人專用的 VPS,老實說比您的日常筆電更適合放 token:如果洩露,您輪換一個 token,而不是您整套設定。
讓它保活的部分:systemd
這是一個能跑的機器人和一個保持執行的機器人之間的分界。建立服務:
# /etc/systemd/system/tgbot.service
[Unit]
Description=Telegram bot (aiogram)
After=network-online.target
Wants=network-online.target
[Service]
User=botuser
WorkingDirectory=/home/botuser/tgbot
EnvironmentFile=/etc/tgbot.env
ExecStart=/home/botuser/tgbot/venv/bin/python bot.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
以一個非 root 使用者(上面的 botuser)跑它,而不是 root——萬一機器人被攻陷,您想讓它被關在盒子裡。然後:
sudo systemctl daemon-reload
sudo systemctl enable --now tgbot
Restart=always 配 RestartSec=3 意味著一次崩潰——Telegram 的一次壞更新、一個未處理的異常、一次 OOM——讓機器人在三秒內回來,而不是讓它死著直到您注意到。即時看它:
journalctl -u tgbot -f
那就是您全部的記錄設定。沒有記錄檔案要輪轉、沒有額外工具——journald 已經有了。
無停機戲劇地更新
當您改程式碼或升級 aiogram:
cd ~/tgbot && source venv/bin/activate
pip install -U aiogram # 如果升級庫
sudo systemctl restart tgbot
journalctl -u tgbot -n 30 --no-pager # 確認它乾淨地回來了
重新啟動讓機器人閃斷一兩秒。對一個輪詢機器人,那對使用者是隱形的——Telegram 把更新排隊、在機器人重連後送達。
輪詢 vs webhook——誠實的版本
這是人們想太多的決定。這是大白話版本:
輪詢(start_polling,上面程式碼用的)讓機器人在一條長連線上問 Telegram「有新東西嗎?」。它除了對外網路什麼都不需要——不用網域、不用 TLS、不用開對內埠。它在 NAT 後面跑得好好的。對絕大多數機器人,這是對的,您該停在這裡。
Webhook 讓 Telegram 把更新推給您,這意味著您必須暴露一個公用 HTTPS 端點。那需要一個網域和一個可達的對內埠——所以要麼一個獨立公用 IP、要麼前面一個反向代理。更多搭建、更多會壞的東西。回報是在大規模下更低的延遲和更少的開銷——成千上萬同時執行使用者、大量更新。
實用規則:在一個 NAT 方案上從輪詢開始。 只有當您真正長過輪詢時才轉 webhook——如果您轉了,那時一個獨立IP才配得上它的位置,因為您需要那個對內 HTTPS 端點。
跑它要花多少
一個輪詢機器人很輕。它在 Telegram 的長輪詢上空閒、對訊息做反應,所以機器大多在等:
- $3 Nano(2 vCPU / 1 GB) —— 對大多數機器人沒問題,甚至相當話癆的。
- $5 Micro(2 vCPU / 2 GB) —— 當機器人帶一個資料庫(SQLite/Postgres)、處理媒體、或服務很多使用者。
- 只有當機器人自己做真活時才更高——影像處理、本機模型、每條訊息的重邏輯。
註冊只用電子郵件,您用 Base 或 Ethereum 上的 USDC 或 USDT 付款——不用卡、不用證件。信用卡也能用,但 on-ramp 有約 $27 的最低額,所以對一個 $3 方案,一次充一小筆餘額、讓續費從裡面扣更順。它是純 CPU、一個在歐盟的資料中心——對機器人不是問題,如果您需要 GPU 或某個特定地區,知道一下也好。
誠實的一句話
一個 Telegram 機器人是您能自託管的最便宜的東西之一:一台 $3 機器、一個 systemd unit、加輪詢,就給您一個熬過崩潰和重新啟動、不用您照看的線上機器人。只有當規模真的逼著您時,才去上 webhook 和更大的方案——而不是因為某個教學告訴您 webhook「更好」。拿那台小機器、把 token 放在環境檔案裡、讓 systemd 管正常執行時間,並——在別的一切之前——跑一遍新 VPS 安全清單,好讓機器本身鎖得嚴實。
準備好託管您的了? 一個 Telegram 機器人幾乎不佔資源——Nano 方案($3/月) 就能 7×24 不費勁地跑它。
評論
目前還沒有評論。歡迎成為第一位。