@loneship/zup
v1.0.0
Published
一个用于发布本地的前后端目录或可执行文件的命令行工具,负责优雅地替换和部署(仅支持pm2部署的产品),并能自动备份旧版本。
Maintainers
Readme
zup
zup 是一个通过 SSH 部署本地构建产物的 CLI。它适合两类场景:
- 上传目录并以原子切换方式发布,例如前端
dist - 上传单个文件并在发布后执行
pm2 reload
使用者只需要安装 Node.js,不需要 TypeScript。
安装
npm install -g @loneship/zup也可以直接使用:
npx @loneship/zup配置文件
默认读取当前目录下的 zup.config.json,也可以通过 --config 指定。
目录模式
适合前端构建目录发布。
{
"ssh": {
"host": "example.com",
"port": 22,
"username": "root",
"password": "your-password"
},
"paths": {
"local": "./dist",
"remote": "/var/www/app"
},
"deployment": {
"mode": "directory",
"preDeployCommand": "npm run build",
"keepBackups": 10
}
}私钥登录
适合使用 SSH key 的服务器。
{
"ssh": {
"host": "example.com",
"port": 22,
"username": "deploy",
"privateKeyPath": "./keys/id_ed25519",
"passphrase": "your-key-passphrase"
},
"paths": {
"local": "./dist",
"remote": "/var/www/app"
},
"deployment": {
"mode": "directory",
"preDeployCommand": "npm run build",
"keepBackups": 10
}
}文件模式
适合单个 Node.js 脚本、Rust 可执行文件等发布。
{
"ssh": {
"host": "example.com",
"port": 22,
"username": "root",
"password": "your-password"
},
"paths": {
"local": "./target/release/my-service",
"remote": "/srv/my-service/current"
},
"deployment": {
"mode": "file",
"preDeployCommand": "cargo build --release",
"keepBackups": 5,
"pm2": {
"appName": "my-service"
}
}
}配置项说明
ssh.host远端主机地址。ssh.portSSH 端口。ssh.usernameSSH 用户名。ssh.passwordSSH 密码,可与私钥认证二选一或同时提供。ssh.privateKey私钥内容,适合直接通过配置注入。ssh.privateKeyPath私钥文件路径。相对路径会基于配置文件所在目录解析,例如./keys/id_ed25519。ssh.passphrase私钥解密口令,仅在使用ssh.privateKey或ssh.privateKeyPath时有效。paths.local本地待发布路径。相对路径会基于配置文件所在目录解析。paths.remote远端正式路径,必须是绝对路径。deployment.mode必填,支持directory或file。deployment.preDeployCommand可选。本地前置命令,在上传前执行。失败时直接中止部署。deployment.keepBackups保留的最近备份数量,默认10,允许为0。deployment.pm2.appName仅file模式可用。切换成功后执行pm2 reload <appName>,等待 5 秒,再执行pm2 list。
使用命令
使用默认配置文件:
zup指定配置文件:
zup --config ./deploy/zup.config.json执行流程
目录模式
- 可选执行本地前置命令,例如
npm run build - 连接 SSH 服务器
- 上传到
remote.tmp.时间戳 - 如果正式目录已存在,先备份到
remote.old.时间戳 - 将临时目录原子重命名为正式目录
- 清理超出
keepBackups的旧备份
文件模式
- 可选执行本地前置命令,例如
cargo build --release - 连接 SSH 服务器
- 上传到
remote.tmp.时间戳 - 如果正式文件已存在,先备份到
remote.old.时间戳 - 将临时文件原子重命名为正式文件
- 如果正式文件不是
.js、.cjs、.mjs,自动执行chmod 755 - 如果配置了
pm2.appName,执行pm2 reload <appName>,等待 5 秒,再执行pm2 list - 清理超出
keepBackups的旧备份
前置命令
deployment.preDeployCommand 适合用来先做本地构建,例如:
npm run buildpnpm buildcargo build --release
规则:
- 在配置文件所在目录执行
- 失败时直接中止部署
- 失败时不会继续 SSH 上传
日志
CLI 会输出带颜色的分层日志,包含:
- 主阶段
- 子步骤
- 文件级上传明细
- 错误详情
典型输出:
[zup] === 开始执行原子部署
[zup] | 部署模式: directory
[zup] | 本地路径: /path/to/dist
[zup] | 正式路径: /var/www/app
[zup] | 临时路径: /var/www/app.tmp.2026-04-10_15.30.00
[zup] | 备份路径: /var/www/app.old.2026-04-10_15.30.00
[zup] ==> 上传临时目录
[zup] -> 递归上传 /path/to/dist -> /var/www/app.tmp.2026-04-10_15.30.00
[zup] | file assets/index.js -> /var/www/app.tmp.2026-04-10_15.30.00/assets/index.js
[zup] === 部署完成远端环境要求
- Linux shell 环境
- 支持常见命令:
mkdir、mv、rm、ls、test - 文件模式如需自动加执行权限,还需要支持
chmod - 文件模式如配置了
pm2,远端还需要安装并可用pm2 paths.remote的父目录需要对当前 SSH 用户可写
常见失败场景
本地路径不存在
directory模式要求paths.local是目录file模式要求paths.local是文件
本地前置命令失败
- 例如
npm run build或cargo build --release执行失败 - 这种情况下不会继续连接服务器
SSH 连接失败
- 主机、端口、用户名、密码、私钥或私钥口令配置错误
- 网络不可达
- 服务器禁止当前认证方式
上传失败
- 远端磁盘空间不足
- 远端目录无写权限
- SFTP 传输中断
备份或切换失败
- 同名临时路径或备份路径已存在
- 远端权限不足
- 目标路径被其他进程占用
PM2 reload 失败
pm2未安装pm2.appName配置错误- reload 后服务启动失败
说明:
pm2 reload失败会让部署失败pm2 list失败只会告警,不会让部署失败
