普贤教程 › 进阶教程
编译与部署
PuXian 的部署比大多数语言简单:编译出一个静态二进制,拷过去,跑起来。没有运行时、没有依赖、没有环境变量魔法。
编译
sh
px build app.px file app/build/app ldd app/build/app
text
app/build/app: ELF 64-bit LSB executable, x86-64, statically linked not a dynamic executable
产物在 <源码目录>/build/<文件名>。拷到任何同架构的 Linux 都能跑:
sh
scp app/build/app deploy@host:/opt/app/bin/app
用 systemd 托管
常驻进程(队列消费者、定时器、监听服务)交给 systemd:
ini
# /etc/systemd/system/myapp.service [Unit] Description=myapp (puxian) After=network.target [Service] Type=simple User=app WorkingDirectory=/opt/app ExecStart=/opt/app/bin/app Restart=always RestartSec=3 StandardOutput=journal StandardError=journal Environment=TZ=Asia/Shanghai [Install] WantedBy=multi-user.target
sh
systemctl daemon-reload systemctl enable --now myapp systemctl status myapp journalctl -u myapp -f
日志别只写文件systemd 下把 stdout/stderr 交给 journal 最省事(
journalctl -u myapp 能直接看)。自己写文件要注意轮转,否则迟早写满磁盘。用 Ma 托管接口
Web 接口不需要自己监听端口。把 .px 放到站点目录,在 Ma 的站点配置里加 px_routes:
json
{
"sites": {
"api.example.com": {
"root": "/data/www/api_example",
"px_routes": [
{"path": "/api/hello", "exact": true, "script": "hello.px",
"methods": ["GET"], "mode": "fast", "timeout_ms": 5000},
{"path": "/api/items", "exact": true, "script": "items.px",
"methods": ["GET", "POST"], "mode": "fast", "timeout_ms": 5000}
]
}
}
}| 字段 | 说明 |
|---|---|
path / exact | 匹配路径;exact: true 表示完全相等 |
script | 相对站点根的 .px 文件 |
methods | 允许的方法;不匹配返回 405 |
mode | auto / fast / compiled |
timeout_ms | 单次执行上限,超时终止子进程 |
改完配置要 reload Ma:
sh
mahesvara --check # 先校验配置
systemctl reload mahesvara静态站点部署
本教程站点就是一个例子:源码在工作目录,生成产物同步到站点根,Ma 只做静态托管。
| 项 | 做法 |
|---|---|
| 站点根 | /data/www/px_dzty_club |
| 生成 | px run gen.px(PuXian 写的静态站生成器) |
| 同步 | rsync -a build/ /data/www/px_dzty_club/ |
| 证书 | Ma 的 cert_watch 自动签发与续期 |
| 缓存 | HTML 默认 5 分钟,改完稍等或用不同查询串验证 |
发布流程(可复用)
px lint+ 断言脚本,确认逻辑没坏;px build,确认能编出来;- 产物跑一次
--version或--selftest; - 备份旧产物(
cp app app.bak-$(date +%Y%m%d-%H%M)); - 替换 + 重启;
- curl 健康检查,看返回码与关键字段;
- 观察日志 5 分钟,有异常立即回滚。
回滚
sh
systemctl stop myapp cp /opt/app/bin/app.bak-20261105-1200 /opt/app/bin/app systemctl start myapp
静态站回滚就是把旧目录 rsync 回去。所以每次发布前先打一个带时间戳的备份——这一步不能省。
健康检查
px
# healthcheck.px —— 给监控系统调 def main(): var t0 = now_ms() var ok = true # 换成真实检查:数据库连通、依赖服务可达 var status = "200 OK" if not ok: status = "500 Internal Server Error" print("Status: " + status) print("Content-Type: application/json") print("") print(json_stringify({"ok": ok, "ms": now_ms() - t0}))
没有三元表达式PuXian 不支持
a if cond else b 这种写法(Python 习惯要改)。先用 if 算好变量,再拼接或输出。常见部署问题
| 现象 | 原因 |
|---|---|
| 启动即退出 | 工作目录不对,相对路径读不到文件;看 journalctl -u |
| 502 | Ma 能连到自己,但脚本超时或崩溃;查 timeout_ms 与 stderr 日志 |
| 改了代码没生效 | Ma 编译缓存命中旧产物;清 cache/pxbuild 或换脚本内容 |
| 证书签发失败 | DNS 未生效或 80 端口被占;先确认域名解析到本机 |
| 时间差 8 小时 | 服务时区是 UTC;unit 里设 TZ=Asia/Shanghai |