资讯动态

AutoJsPro自建服务器实战:Node.js+SQLite实现设备鉴权与脚本分发

发布时间:2026/10/8 19:44:39 来源:尧图企业网站定制
简介围绕AutoJsPro的自建服务器需求资源定位于帮助用户完成从环境搭建到远程控制配置的完整流程适合希望脱离官方云服务、实现自主控制的Android自动化脚本开发者。压缩包共9个文件、约344.42MB主要包含AutoJsPro及辅助工具等4个APK安装包、Node.js与Python自建服务器所需的exe/json/hosts配置文件以及mp4视频教程和txt图文教程能够覆盖服务器配置、ProxyPin代理设置等关键环节。已有13612人学习下载足见其实用性。通过这套资料读者可获得AutoJsPro Pro 9.3.11安装包、AJServer辅助APK、自建服务器程序及视频加文本的详细指导按教程逐步操作即可搭建个人服务器进而实现远程控制和更灵活的自动化任务。1. AutoJsPro 自建服务器把群控设备的命脉抓回自己手里凌晨两点被告警电话叫醒十二台测试机的 AutoJsPro 全部掉线排查到大天亮才发现是官方服务器在做维护授权接口一直连不上。脚本矩阵写得再漂亮授权服务一摆手就是零。后来我把整套授权校验、脚本下发和日志回传搬到了一台内网小服务器上只要网络通设备自己就能闭环。这就是 AutoJsPro 自建服务器在你自己的机器上搭一个 HTTP 服务替代官方鉴权服务器的角色让 AutoJsPro 客户端连你而不是看外部服务脸色。它适合工作室批量手机、测试团队做群控脚本如果只是单机调试官方直连就够没必要折腾。2. 自建服务器到底在“建”什么鉴权、分发与日志回传2.1 一台服务器替代官方的三张脸授权、仓库、日志很多人把“自建服务器”误理解成部署一个静态网页放脚本下载其实它至少要承担三个角色少一个都会让整个链路变成半残废。第一是鉴权授权服务。AutoJsPro 客户端在启动脚本前会向一个服务器地址请求授权。官方模式下这个地址是官方服务器自建模式就是把地址换成你自己的。你的服务器需要一个设备注册表里面至少包含设备序列号、授权码、设备状态、最后在线时间。这样做的好处是设备断网、授权码到期、设备被禁用你都能从服务端一张表里看明白而不是去每一台手机上翻设置。第二是脚本仓库。脚本和资源文件不能靠微信群传来传去服务器上按任务名和版本号存放 JS 文件设备启动时拉取与自己匹配的版本。仓库不需要做得多复杂脚本文件落在磁盘上元数据放进 SQLite 就够。第三是日志回传。脚本跑完把执行结果、报错信息 POST 回服务器集中查看。设备侧 console 只能单机看回传之后不用一台台摸过去哪个任务挂了服务器页面一眼就能定位。这就是我常说的别把脚本当黑匣子日志回传是最便宜的后悔药。2.2 选型理由Node.js SQLite别一上来就上重量级网关自建服务器用什么技术栈常见选择有 Node.js、Go、Python、Nginx PHP 这类组合。我一般会选 Node.js SQLite理由很直接AutoJsPro 本身跑的就是 JavaScript服务端也用 JavaScript脚本团队改起来顺手不会出现“手机端会写 JS、服务端看不懂 Go”的割裂感。单进程 HTTP 服务加单文件 SQLite不依赖容器也能扛得住几十台设备的轮询。设备量只有几十台时直接监听 0.0.0.0:8080 就够了没必要先上 Nginx 做网关。Nginx 的价值在于你后续要统一域名、挂证书、做日志切分那时候再把它架在前面不迟。Go 并发确实强但代码模板多增删一个接口的成本明显更高Python 也能做只是部署环境容易踩版本坑。还有一个大家容易忽略的点这个服务的压力模型是“低频轮询 少量写”跟高并发 Web 完全是两码事。每台设备每 30 到 60 秒请求一次100 台设备峰值也就每秒几个请求内存占用 20MB 级别。选型时别按互联网大厂的标准给自己加戏。2.3 接口协议与 token 生命周期注册、换取、续期、失效接口设计不需要花哨HTTP JSON 就够了。设备端和 PC 端都能用 curl 复现问题排查起来比自定义 TCP 协议省心太多。我一般会保留这么几个接口接口路径方法作用/api/device/registerPOST设备注册传序列号与授权码返回 token/api/device/authPOSTtoken 校验与续期失败时设备端要重新注册/api/script/listGET按版本返回脚本清单名称、版本、url、md5/api/script/uploadPOST上传脚本文件管理端使用/api/script/logPOST接收脚本执行日志/api/healthGET健康检查压测和告警用这套接口的核心链路是“注册换 tokentoken 换脚本”。token 有效期设置很关键后面避坑章节会专门讲。设备启动时先用缓存里的 token 调用 /api/device/auth返回 200 就继续干活返回 401 说明 token 过期或不合法设备端要自动重新走一遍注册流程。整个生命周期里设备端不能因为一次网络抖动就直接退出任务必须留缓存和重试的余地。3. 从零搭建最小可用鉴权服务Node.js SQLite 的六十行代码3.1 初始化项目三个依赖就够服务端只依赖三个包express 负责 HTTP 路由better-sqlite3 负责存储jsonwebtoken 负责生成和校验 token。这个组合已经能覆盖注册、鉴权、脚本清单、日志上报四条核心链路。mkdir /opt/autojs-server cd /opt/autojs-server npm init -y npm install express better-sqlite3 jsonwebtoken选 better-sqlite3 而不是 sqlite3 的原因很简单它是同步 API几十台设备的并发量根本不需要回调那一套异步写法代码短一半出错的概率也低。jsonwebtoken 是 Node 生态里最通用的 JWT 库不引入额外概念token 签名、过期时间都在一个函数里解决。3.2 核心代码注册、鉴权、脚本清单、日志上报下面是一份可以直接跑起来的最小实现覆盖了自建服务器最核心的部分。// server.js const express require(express); const jwt require(jsonwebtoken); const Database require(better-sqlite3); const db new Database(autojs.db); db.pragma(journal_mode WAL); db.pragma(busy_timeout 5000); db.exec( CREATE TABLE IF NOT EXISTS devices ( serial TEXT PRIMARY KEY, license_code TEXT NOT NULL, status INTEGER DEFAULT 1, last_seen_at INTEGER ); CREATE TABLE IF NOT EXISTS scripts ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, version TEXT NOT NULL, url TEXT NOT NULL, md5 TEXT NOT NULL, created_at INTEGER ); ); const app express(); app.use(express.json()); const SECRET process.env.AUTOSERVER_SECRET || change-me-in-prod; const DEVICE_VERSION process.env.SCRIPT_VERSION || 1.0.0; const TOKEN_TTL 7d; function signDevice(serial) { return jwt.sign({ serial }, SECRET, { expiresIn: TOKEN_TTL }); } app.post(/api/device/register, (req, res) { const { serial, licenseCode } req.body || {}; if (!serial || !licenseCode) return res.status(400).json({ error: serial and licenseCode required }); const s String(serial).trim().toLowerCase(); db.prepare( INSERT INTO devices (serial, license_code, last_seen_at) VALUES (?, ?, ?) ).run(s, licenseCode, Date.now()); res.json({ ok: true, token: signDevice(s) }); }); app.post(/api/device/auth, (req, res) { const { token } req.body || {}; try { const payload jwt.verify(token, SECRET); const row db.prepare(SELECT status, license_code FROM devices WHERE serial ?).get(payload.serial); if (!row || row.status ! 1) return res.status(403).json({ error: device disabled }); db.prepare(UPDATE devices SET last_seen_at ? WHERE serial ?).run(Date.now(), payload.serial); res.json({ ok: true, serial: payload.serial }); } catch (e) { res.status(401).json({ error: token expired or invalid }); } }); app.get(/api/script/list, (req, res) { const rows db.prepare(SELECT name, version, url, md5 FROM scripts WHERE version ?).all(DEVICE_VERSION); res.json({ ok: true, scripts: rows }); }); app.post(/api/script/log, (req, res) { console.log(req.body); // 正式环境可以落库或推到告警群 res.json({ ok: true }); }); app.get(/api/health, (req, res) { res.json({ ok: true, uptime: process.uptime() }); }); const PORT process.env.PORT || 8080; app.listen(PORT, 0.0.0.0, () console.log(autojs server listening on ${PORT}));这段代码的主链路是设备 POST 序列号和授权码到 register拿到 token后续每次调用 auth 携带 token服务端验签后返回设备状态。脚本清单通过 version 字段控制设备端只拉取与自身匹配的版本。参数说明PORT 默认 8080如果服务器上已有服务占用改成 18080 这类不常用端口AUTOSERVER_SECRET 生产环境必须换成随机长字符串否则 token 可以被伪造等于整个鉴权形同虚设SCRIPT_VERSION 是当前要下发的脚本版本号配合脚本管理端使用TOKEN_TTL 是 token 有效期7 天是一个比较平衡的默认值既能避免一次掉线后长期失联也不会让设备频繁重注册。3.3 WAL 并发与 token 密钥两个必调的运行参数better-sqlite3 默认的 journal 模式在并发写时会报 SQLITE_BUSY多台设备同时注册的场景极易触发。代码里已经用 db.pragma 做了两件事journal_mode 改成 WALbusy_timeout 设成 5000 毫秒。WAL 允许读操作和写操作并行busy_timeout 让对方等待而不是直接报错。这两个 pragma 是 SQLite 在服务端场景下的标配忘了哪一行都会在并发时翻车。token 密钥不要写在代码里。我踩过一次把 SECRET 明文留在 server.js 里后来改配置时差点把带密钥的文件提交进仓库。更好的做法是用环境变量注入systemd 的 Environment 字段、Docker 的 -e 参数都可以代码里只留一个兜底默认值让服务能启动但生产环境必须覆盖它。4. 客户端对接与脚本分发改地址、打版本、留缓存4.1 把 AutoJsPro 的服务器地址指向自建服务服务端写好之后要做的关键一步是让 AutoJsPro 客户端把请求地址从官方服务器改成自建服务器。常见做法是在客户端的服务器设置或连接配置里把地址字段改成http://192.168.1.100:8080这种格式保存后重启客户端首次请求就会走自建服务。设备端和服务端要约定好通信的 JSON 结构。我一般建议客户端配置文件里保留这样一段内容{ server: http://192.168.1.100:8080, device: { serial: xxxx, licenseCode: autojs-license-code, pollIntervalSec: 60 } }serial 是设备唯一标识不要直接用 mac 地址Android 设备的序列号更适用licenseCode 是 AutoJsPro 的授权码pollIntervalSec 是轮询间隔单位秒。首次注册成功后设备端要把 token 存到本地存储里下次启动优先用缓存的 token而不是重新注册一遍。4.2 脚本上传与版本管理一个 version 字段控制更新脚本仓库不能只靠人工覆盖文件不然版本根本没法回溯。我一般会在服务端补一个简单的上传接口字段就三个name 表示任务名version 表示版本号file 表示脚本文件本身。上传命令大概长这样curl -F filetasks/daily.js \ -F namedaily \ -F version1.0.3 \ http://192.168.1.100:8080/api/script/upload服务端收到文件后把它存到uploads/daily/1.0.3/daily.js同时在 scripts 表里插入一条记录。设备的 /api/script/list 返回的 URL 是这个文件的访问地址md5 字段让设备端在下载完整后做校验避免网络传输导致文件截断脚本跑到一半才报语法错误的坑。版本号建议用语义化格式1.0.3 这种不要用日期。日期格式在回滚时很难判断哪个版本是真正的前一版。每次发布新脚本在管理端把 SCRIPT_VERSION 环境变量改到新版本号重启服务设备端下一次轮询就会拿到新版本的下载地址。回滚时把环境变量改回去即可这个设计比删文件重传要干净得多。4.3 轮询策略与离线缓存断网时任务照跑自建服务器并不等于设备永远在线设备端反而要考虑断网的兜底。轮询策略我一般这样设计设备每 60 秒调用一次 auth 接口200 就继续401 就重新注册换 token网络异常就跳过本轮继续跑本地已有的任务不中断不退出。// 设备端断网保护示意代码 async function syncWithServer() { try { const authRes await http.post(/api/device/auth, { token: storage.get(token) }); if (authRes.statusCode 401) { const reg await http.post(/api/device/register, { serial, licenseCode }); storage.set(token, reg.token); } const scriptList await http.get(/api/script/list); if (scriptList.currentVersion ! localVersion) { // 下载新脚本校验 md5 后替换本地文件 } } catch (e) { // 网络不通继续跑本地缓存版本不阻塞任务队列 } }这段示意代码的重点是 catch 分支网络异常时设备绝不能退出脚本而是跳过同步继续执行本地任务。这里用的是 AutoJsPro 环境里的 http 模块具体接口名可能因版本不同略有差异但思路是一样的同步与执行解耦同步失败不影响执行。我把这个策略叫“断网照跑”对群控设备来说这比高可用服务器本身更重要。5. 自建服务器避坑清单五条真实翻车记录5.1 连不上服务器端口监听地址和防火墙的静默拦截现象手机端或 PC 端 IDE 配置好自建服务器地址后一直报“无法连接到服务器”但服务器本机 curl 明明能通。原因大部分情况下是 Node 服务监听在了 127.0.0.1 上只允许本机访问或者是服务器防火墙没有放行对应端口。前者属于代码层面问题后者属于系统配置问题。解决代码里 listen 的地址必须是0.0.0.0代表监听所有网卡换成127.0.0.1就只有本机能连。防火墙放行规则各系统不同常见做法是用 ufw 执行ufw allow 8080/tcp。验证时不要只在服务器本机 curl从另一台机器执行curl http://192.168.1.100:8080/api/health能返回 JSON 才说明真的对外开放了。5.2 设备集体掉线token 过期时间与设备时钟共同作用现象设备运行一段时间后集体掉线但又不像断电日志里全是 401 或 token 过期。原因token 有效期设置太短是一个原因我第一次把这个值配成 3600 秒结果设备每隔一小时就要重新注册一次。更隐蔽的是设备时间不同步导致的 JWT 过期误判JWT 的 exp 字段是基于服务器时间计算的设备端系统时间偏差超过几分钟校验就会失败。解决token 有效期按设备的实际轮询节奏设置建议至少 7 天设备端必须开启系统自动对时。如果设备数量多可以在 auth 接口里容忍少量时间偏移但最可靠的办法还是让设备系统时间准确。5.3 SQLITE_BUSY多设备并发注册把数据库写锁现象多个设备同时首次注册时部分请求返回 500服务端日志里出现 SQLITE_BUSY。原因better-sqlite3 默认事务模式在并发写时会锁定数据库多个写操作挤在一起时后面的请求只能报错。这个问题在单设备调试时完全不会暴露一旦设备数量上到二十台以上就开始频繁出现。解决在打开数据库后立刻执行两个 pragmajournal_mode WAL和busy_timeout 5000。WAL 模式让读写不再互相阻塞busy_timeout 让写请求在锁释放前等待 5 秒而不是直接失败。这两个参数必须放在首次建表之前执行。5.4 脚本拉到手机端报语法错误CRLF 与 UTF-8 BOM 的锅现象脚本在电脑上编辑、测试都正常但通过自建服务器下发到手机端后AutoJsPro 直接报语法错误有时报错行号还不对。原因多数编辑器在 Windows 上默认把换行符存成 CRLFAutoJsPro 的脚本引擎对 CRLF 的容错有限。另一个常见原因是编辑器存成了带 UTF-8 BOM 的格式BOM 字符被当成脚本开头的一部分引擎直接解析失败。这两个问题叠加起来非常隐蔽因为把文件复制到电脑上再打开看起来毫无异常。解决上传前统一把脚本转成 LF 换行并去掉 BOM。可以用编辑器设置“保存为 UTF-8 无 BOM”也可以用命令批量转换sed -i s/\r$// tasks/daily.js sed -i 1s/^\xEF\xBB\xBF// tasks/daily.js服务端在上传接口里也做一道校验检查文件开头三个字节是否是 EF BB BF是就直接剔除。5.5 证书与明文二选一别让一台旧手机的时钟毁掉全部现象局域网内大部分设备连接正常但总有几台旧手机一直报 SSL handshake failed其余设备完全正常。原因这些旧手机的系统时间没有开启自动对时停留在几个月甚至几年前。HTTPS 握手时证书有效期判断失败整个连接被拒绝。这不是服务器的问题是设备端时钟的问题。解决设备端开启自动对时手动校准一次。服务器这边如果所有设备都在同一个局域网内评估一下风险后可以先用 HTTP 跑起来如果服务器要暴露到公网必须上 HTTPS证书用 Let’s Encrypt 这类免费方案即可。别为了迁就旧设备放弃 HTTPS也别因为一台旧设备时钟不对就怀疑证书配置——先查时间再查证书。6. 自建服务器上生产前再做三件事进程守护、批量导入与压测6.1 systemd 常驻重启也不掉线开发时直接在终端跑node server.js没问题上生产后服务器一重启服务就没了设备那边全线失联。我一般会把它包成 systemd 服务[Unit] DescriptionAutoJsPro self-host server Afternetwork.target [Service] ExecStart/usr/bin/node /opt/autojs-server/server.js Restartalways EnvironmentAUTOSERVER_SECRETyour-random-secret EnvironmentPORT8080 WorkingDirectory/opt/autojs-server Userautojs Groupautojs [Install] WantedBymulti-user.targetRestartalways保证进程异常退出后自动拉起环境变量统一放在 unit 文件里密钥不散落在代码中。保存后用systemctl daemon-reload systemctl enable autojs-server设置开机自启。6.2 CSV 批量导入设备不再一台台手输序列号新手阶段我是一台台手动注册的设备一多就想骂人。批量导入其实很简单CSV 两列一列序列号一列授权码循环调注册接口while IFS, read -r serial license; do curl -s -X POST http://127.0.0.1:8080/api/device/register \ -H Content-Type: application/json \ -d {\serial\:\$serial\,\licenseCode\:\$license\} echo done devices.csv序列号列注意去掉空格和大小写问题服务端注册接口里统一做 trim 和 toLowerCase设备端也同样处理两边对不上就永远鉴权失败。6.3 autocannon 压测与验收标准压测直接打 /api/health 接口用 autocannon 跑 10 秒20 个并发连接npm install -g autocannon autocannon -c 20 -d 10 http://127.0.0.1:8080/api/health这个场景下 QPS 不是核心指标重点看有没有 5xx 响应。几十台设备的轮询压力远到不了瓶颈能扛住几百并发无 5xx基本就算过关。我自己的验收标准是压测 10 分钟不重启、不出现 SQLITE_BUSY、平均响应延迟低于 50 毫秒。这套服务我前后搭过三轮最深的教训是第一次上线时把 token 有效期配成 30 分钟第二天早上 12 台设备全部掉线群里告警响成一片。后来改成 7 天有效期加设备端 401 自动重注册再也没出过集体掉线的事。自建服务器本身不难难的是把每一个可能导致整片设备瘫痪的小参数都提前想到。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑