px普贤教程PuXian
普贤教程 › 进阶教程

编译与部署

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
modeauto / 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 分钟,改完稍等或用不同查询串验证

发布流程(可复用)

  1. px lint + 断言脚本,确认逻辑没坏;
  2. px build,确认能编出来;
  3. 产物跑一次 --version 或 --selftest;
  4. 备份旧产物(cp app app.bak-$(date +%Y%m%d-%H%M));
  5. 替换 + 重启;
  6. curl 健康检查,看返回码与关键字段;
  7. 观察日志 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
502Ma 能连到自己,但脚本超时或崩溃;查 timeout_ms 与 stderr 日志
改了代码没生效Ma 编译缓存命中旧产物;清 cache/pxbuild 或换脚本内容
证书签发失败DNS 未生效或 80 端口被占;先确认域名解析到本机
时间差 8 小时服务时区是 UTC;unit 里设 TZ=Asia/Shanghai