
传统运维脚本的宿命往往是:写完一个 check_disk.py,再写一个 check_mem.py,然后用 crontab 串起来,输出一堆 txt,最后靠人肉登录服务器去翻。问题不在于脚本写得不好,而在于链路是断的——采集、存储、调度、展示各在一处,没有形成闭环。
"全栈运维"不是要求运维去写前端框架,而是用同一门语言覆盖整条链路:
采集 → 存储 → 调度 → 展示
↑________________________↓
反馈与告警Python 恰好在这四段都有足够成熟的库,且不需要切换心智模型。下面用尽可能少的代码,走一遍完整流程。
巡检的本质是"对 N 台机器执行同一条命令"。新手会写 for host in hosts:,100 台机器串行 SSH,一轮下来十分钟。
用 asyncio 把 SSH 变成并发任务,代码量几乎没有增加:
import asyncio
async def run(host, cmd):
p = await asyncio.create_subprocess_shell(
f"ssh -o BatchMode=yes -o ConnectTimeout=5 {host} {cmd}",
stdout=asyncio.subprocess.PIPE,
)
out, _ = await p.communicate()
return host, out.decode().strip()
async def gather(hosts, cmd):
return await asyncio.gather(*(run(h, cmd) for h in hosts))
print(asyncio.run(gather(["web01", "web02", "db01"], "uptime")))十行代码,100 台机器和 3 台机器的耗时几乎一样——瓶颈从"机器数量"变成了"单次 SSH 延迟"。
这里刻意用系统
ssh而非paramiko:免密、跳板机、ProxyCommand 这些配置复用现成的~/.ssh/config,不用在代码里重新实现一遍。
很多人一上来就上 Prometheus + InfluxDB,结果发现 90% 的查询只是"最近 20 条巡检结果"。这种场景,SQLite 足够,而且零运维成本。
用 SQLModel(SQLAlchemy + Pydantic 的封装)定义一个表,代码短到不像 ORM:
from datetime import datetime
from sqlmodel import SQLModel, Field, Session, create_engine
class Metric(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
host: str
load: float
ts: datetime = Field(default_factory=datetime.now)
engine = create_engine("sqlite:///ops.db")
SQLModel.metadata.create_all(engine)
def save(host, load):
with Session(engine) as s:
s.add(Metric(host=host, load=load))
s.commit()表结构即代码,改字段就是改一行类型注解,不用手写 DDL。等数据量真的涨到 SQLite 扛不住,再把 create_engine 的 URL 换成 PostgreSQL 即可,上层逻辑一行不用动。
运维脚本最难用的地方是"只有写它的人会用"。把它包成 HTTP 接口,价值立刻不一样——浏览器能看,Grafana 能接,告警系统能调。
from fastapi import FastAPI
from sqlmodel import select
app = FastAPI()
@app.get("/metrics")
def metrics(limit: int = 20):
with Session(engine) as s:
return s.exec(select(Metric).order_by(Metric.ts.desc()).limit(limit)).all()启动就一句:uvicorn main:app --host 0.0.0.0 --port 8000。
/docs 路径自动生成交互式文档,前端同事要对接时直接甩链接,不用再写接口说明。
crontab 的问题是分散——crontab -l 在每台机器上都不同,出了事没人知道任务到底跑没跑。把调度收进应用进程:
from apscheduler.schedulers.asyncio import AsyncIOScheduler
sched = AsyncIOScheduler()
@sched.scheduled_job("interval", minutes=1)
async def collect():
for host, out in await gather(HOSTS, "cat /proc/loadavg"):
save(host, float(out.split()[0]))
sched.start()好处是:任务定义和业务代码在同一个仓库,能打日志、能加异常捕获、能被 /health 接口观测。crontab 里那行 >> /dev/null 2>&1 造成的失联,从此消失。
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]requirements.txt 里也就四五个包:fastapi、uvicorn、sqlmodel、apscheduler。
必须说清楚它不适合什么:
Python 全栈运维的定位是中间层:比 shell 脚本更可维护,比 Ansible 更灵活,比完整监控平台更轻。它擅长的是那些"用现成工具太重、用 shell 又太脆"的活儿。
整条链路的核心代码加起来不到 60 行,却完成了:并发采集、结构化存储、HTTP 展示、进程内调度、容器化部署。
全栈的意义不在"什么都会",而在于消除语言和工具之间的接缝。当采集、存储、调度、展示都在同一个进程、同一个仓库、同一套类型系统里时,运维系统才真正变成了"软件",而不是一堆散落的脚本。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。