用 AtomCode 在云服务器上 10 分钟"造"一个服务器资产巡检 API —— 一次真实的 Headless 实战
本文为「码动四季」夏季征文 ·实战体验类投稿。文中所有命令与输出均来自真实机器操作,主机账号/密码等敏感信息已脱敏。
0. 为什么写这篇
我是做 DevOps / 运维开发的,日常里最常被问到的一类需求是:“给我一个能随时看服务器健康度的接口”。这类需求不大,但手写起来琐碎(读/proc、算 CPU 采样、拼 JSON、写测试、配 systemd)。正好最近在玩AtomCode——一款「开源 + 多模型 + 免费 Token」的全自动 AI 编码助手,我干脆拿它做一次端到端实战:在一台真实云主机上,用 AtomCode 的headless(无人值守)模式从零生成、自测、验证一个轻量巡检服务,并把全过程如实记下来。
本文所有输出来自真实环境:Ubuntu 22.04.3 LTS(2 vCPU / 3.8GB RAM),AtomCode5.0.0,默认模型deepseek-v4-flash。
1. 环境速览:AtomCode 是怎么"住"在机器上的
我通过 SSH 登录云主机后,先确认 AtomCode 的部署形态:
$cat/etc/os-release|head-2PRETTY_NAME="Ubuntu 22.04.3 LTS"$ atomcode--versionatomcode5.0.0(unknown)$ atomcode status Loggedinas: cpyaxjq(66612fcc2da91e28f2501347)Name: cpyaxjq Email: cpyaxjq@noreply.gitcode.com Auth file: /root/.atomcode/auth.toml $ systemctl is-active atomcode-webui atomcode-login active active $ ss-ltnp|grep13457LISTEN040960.0.0.0:13457... users:(("atomcode",pid=9510,fd=9))几个关键事实:
- 登录方式:AtomGit OAuth,一条
atomcode login完成授权并领取CodingPlan 免费模型额度(无需自备 API Key)。 - 默认模型:
AtomGit-deepseek-v4-flash,base_url=https://llm-api.atomgit.com/v1,上下文窗口 100 万 token;视觉走Qwen3-VL-8B-Instruct,联网检索走 Exa。 - 常驻服务:
atomcode-webui(浏览器交互,端口 13457)、atomcode-login(OAuth 监听)。也就是说它既能当命令行工具,也能当常驻服务 / IDE 守护进程(daemon子命令)使用。
2. AtomCode 能力地图(CLI 视角)
┌──────────┐ SSH / Terminal ┌─────────────────────────────────┐ │ 开发者 │ ─────────────────▶ │ atomcode (CLI v5.0.0) │ └──────────┘ │ │ │ ├─ login / logout / status │ │ ├─ webui (浏览器交互 :13457) │ │ ├─ daemon (IDE 集成 HTTP) │ │ ├─ mcp (MCP 服务器管理) │ │ ├─ plugin (skill / 命令插件) │ │ ├─ hooks (生命周期钩子) │ │ ├─ fixissue(修 AtomGit issue) │ │ └─ upgrade / rollback (热升级) │ └──────────────┬───────────────────┘ │ headless: --prompt-file -y ▼ ┌─────────────────────────────────┐ │ deepseek-v4-flash @ AtomGit │ │ (1M ctx, 免费 CodingPlan 额度) │ └─────────────────────────────────┘Headless 模式是本文重点,命令形态为:
atomcode --prompt-file task.md-y--no-telemetry--prompt-file:从文件读任务(比-p更适合多行、带代码的复杂需求)。-y / --dangerously-skip-permissions:自动放行所有工具调用(写文件、跑命令)。这正是自动化跑任务的前提,否则它会卡在权限确认上。--no-telemetry:关闭遥测,输出更干净。
3. 实战:一句话需求 → 一个可上线服务
我把需求写进prompt.md,核心约束是:
- 在
/root/atomcode_demo建一个 Flask 服务server-probe,含/healthz、/api/metrics、/api/info三个接口; - 不依赖 psutil,必须用标准库读
/proc与系统命令(我有意加的约束,逼它写可移植代码); - 自带 pytest 测试、自带 systemd unit;
- 必须真跑 pytest 并 curl 验证,把结果写进 README。
然后一行命令把任务交给 AtomCode(用timeout 540兜底,避免长任务失控):
cd/root/atomcode_demo&&timeout540\atomcode --prompt-file prompt.md-y--no-telemetry-v\>run.log2>&13.1 AtomCode 的"自主执行"长什么样
它不是一个简单的代码补全,而是一个有规划、会自测、会纠错的 Agent。从run.log统计:
- 总耗时375.9 秒,消耗514.70K tokens(缓存命中率约 97%);
- 27 个对话轮次(turns),36 次工具调用;
- 工具调用分布:
bash×15、todowrite×13(自己拆任务清单)、write_file×5、edit_file×1、read_file×1、list_directory×1。
换句话说,它自己列了待办、写了文件、建了 venv、装了依赖、跑了 pytest、还用 curl 做了接口联调。几个有代表性的动作:
[tool→ bash] cd /root/atomcode_demo && python3 -m venv .venv && \ source .venv/bin/activate && pip install -r requirements.txt [tool→ bash] python -m pytest test_api.py -v [tool→ bash] .venv/bin/flask --app app run --host 127.0.0.1 --port 8088 & \ sleep 2 && curl ... /api/metrics [tool→ edit_file] 把验证结果写回 README.md 的 "## 验证记录"3.2 它写出来的核心代码(节选)
app.py里 CPU 采样与内存解析都是直接读/proc,不依赖第三方库:
defget_cpu_percent():"""Sample CPU usage over ~1 second."""total1,idle1=_get_cpu_stat()time.sleep(1)total2,idle2=_get_cpu_stat()delta_total=total2-total1 delta_idle=idle2-idle1ifdelta_total==0:return0.0returnround(100.0*(1.0-delta_idle/delta_total),1)defget_memory():"""Parse /proc/meminfo, return (total_mb, used_mb, percent)."""data={}forlinein_read_proc("/proc/meminfo").split("\n"):k,v=line.strip().split(":",1)data[k]=int(v.strip().split()[0])# kBtotal=data["MemTotal"]available=data.get("MemAvailable",data["MemFree"])used=total-available percent=round(100.0*used/total,1)iftotal>0else0.0returnround(total/1024,1),round(used/1024,1),percent/api/info还顺手把 AtomCode 自己的版本也带上了(执行atomcode --version),很有"元认知"味道。
3.3 验证:不是"写完就交差"
AtomCode 自己跑了 pytest:
test_api.py::TestHealthz::test_healthz_returns_ok PASSED [ 33%] test_api.py::TestMetrics::test_metrics_returns_required_fields PASSED [ 66%] test_api.py::TestInfo::test_info_returns_required_fields PASSED [100%] 3 passed in 1.12s为"双重保险",我自己又启动服务 curl 了一遍(端口 8089,避免和它用的 8088 冲突):
$curl-s-w'\nHTTP %{http_code}\n'http://127.0.0.1:8089/healthz{"status":"ok"}HTTP200$curl-shttp://127.0.0.1:8089/api/metrics{"hostname":"lavm-cw9k5dvspp","cpu_count":2,"cpu_percent":2.0,"mem_total_mb":3923.6,"mem_used_mb":625.6,"mem_percent":15.9,"disk_root_total_gb":58.8,"disk_root_used_gb":30.5,"disk_root_percent":51.8,"load_avg":[0.0,0.04,0.07]}HTTP200$curl-shttp://127.0.0.1:8089/api/info{"os_name":"Linux","kernel":"5.15.0-60-generic","python_version":"3.10.12","atomcode_version":"atomcode 5.0.0 (unknown)"}HTTP200三个接口全部HTTP 200,返回的是这台机器真实的 hostname、内存、磁盘、内核数据。一个从零开始、含测试、含部署单元的小服务,就这样在 6 分钟出头里"长"出来了。
4. 踩坑记录(都是真踩的)
坑 1:auto_update 会"偷偷"升级,且破坏旧命令参数。
我第一次执行atomcode plugin list时,它直接联网下载并原地升级 4.26.0 → 5.0.0(因为config.toml里auto_update = true)。升级后我发现之前记忆里的--max-turns 30参数直接报unexpected argument——v5.0.0 已经把它从顶层选项移除了。
✅ 建议:用--dev启动可临时禁用自动升级;生产机器建议在 seed-config 里关掉auto_update并锁定版本,避免"今天写的脚本明天就跑不了"。
坑 2:headless 必须用-y,否则会卡在权限确认。
不加-y时,它每写一个文件都要你确认。自动化场景务必加-y(等价于"全放行"),当然前提是任务边界你已经用 prompt 约束清楚。
坑 3:root 下运行有安全告警。
日志里有一条[warning] Running with Administrator privileges — model may have access to system files.。Headless 自动放行 + root 权限 = 模型有能力改系统文件。强烈建议:生产 / CI 里用普通用户跑 AtomCode,或配合--disable-tools收掉危险工具。
坑 4:模型会"偷懒"用重依赖。
初版它想直接import psutil,被我在 prompt 里显式禁止后才改读/proc。这也提醒我们:给 Agent 的约束要写死,越具体越好,否则它会选"最省事但最不通用"的实现。
5. 体验总结:AtomCode 适合谁、强在哪
- 开源 + 多模型 + 免费 Token:CodingPlan 模型额度对日常脚本、运维工具、小项目原型非常够用;开源属性意味着你能
upgrade/rollback、能看生态、能二次开发。 - Headless 是可以进 CI 的:
--prompt-file+-y让它天然适合"定时生成 / 修复代码"“issue 自动修”(fixissue子命令直接吃 AtomGit issue)。 - 生态完整:WebUI、IDE
daemon、MCP、plugin/hooks、subagent(配置里max_concurrent=3)一应俱全,不是一个"只会补全"的工具。 - 不足 / 注意:自动升级机制偏激进(见坑 1),多模型路由、长任务稳定性仍需打磨;headless 的权限模型建议生产环境务必收紧。
一句话:如果你想要一个"能自己列计划、写代码、跑测试、还能进流水线"的开源编码 Agent,AtomCode 值得现在就装上玩一玩。
投稿类别:实战体验类 · 我用 AtomCode 开发 XX 项目的真实记录
主题契合:开源 AI 编码工具 / 运维自动化实战
原创声明:本文所有命令与输出均来自作者真实机器操作,AI 辅助占比低于 30%。