您好,我咨询一下 engines.execScriptFile 本地文件调度方案的稳定性,我的整体架构如下:
常驻云端守护主脚本,通过轮询读取手机本地 JSON 指令文件接收 APP 下发任务;
收到微信销售任务后,调用 engines.execScriptFile 读取手机自定义目录 /sdcard/WLmob_AI/business/wechat/wechat_sales.js 本地业务脚本;
使用 arguments 把 JSON 任务配置透传给子脚本,子脚本通过 engines.myEngine().execArgv 获取参数执行业务流程。
现有 3 个核心问题请教:
云端常驻守护脚本调用 execScriptFile 读取手机内部存储自定义文件夹下的 JS 文件,能否稳定完整运行?会不会出现子脚本瞬间结束、运行时长 0 秒、逻辑不执行的问题?
execScriptFile 通过 arguments 传递字符串参数、子脚本用 execArgv 接收的传参方式,是否官方长期兼容、无底层 bug?
手机重启、Hamibot 后台完全关闭重开后,读取 /sdcard/WLmob_AI/ 自定义文件夹内文件是否存在权限拦截,需要额外做权限适配吗?
补充背景:之前使用 engines.execScript("云端识别码","",{}) 远程拉起方案,会固定出现子脚本秒退出无法完整执行,因此切换成本地文件方案,想确认这套架构是否可行,避免反复调试重构。
另外,请给出:实现的技术参考

HAMI_6893877807 · 4 小时前

回答

Hamibot AI
1
· 4 小时前

你的架构设计思路是合理的,把远程脚本替换为本地文件执行,能从根本上规避网络加载带来的不确定性。engines.execScriptFile 是 Hamibot 提供的一个稳定、底层的脚本调度接口,完全可以支撑你这种常驻守护 + 按需拉取本地业务脚本的模式。

下面针对你的三个核心问题逐一说明。


1. execScriptFile 能否稳定完整运行?会不会出现子脚本瞬间结束、逻辑不执行?

engines.execScriptFile 本身是稳定可靠的,它会像正常启动一个脚本那样去执行指定路径的 JS 文件,不会因为调用方式本身而导致子脚本瞬间退出或逻辑不执行

你之前遇到的 engines.execScript 远程脚本秒退问题,通常是网络加载超时、云端脚本内容为空或脚本自身报错所致。换成本地文件后,这些风险都不存在了。如果子脚本依然出现 0 秒结束,常见原因有:

  • 脚本文件路径错误,execScriptFile 找不到文件时会静默失败,建议调用前用 files.exists(path) 校验。
  • 业务脚本内部没有阻塞逻辑(如没有使用 setIntervalevents.on 等),执行完最后一行代码后脚本自然退出。如果你的业务脚本是“一次性执行完就结束”的任务,这是正常行为,守护脚本只需监听 ScriptExecution 的退出事件即可。
  • 业务脚本在执行过程中抛出了未捕获的异常,导致脚本终止。你可以在业务脚本最外层包裹 try...catch 并把错误写入日志,方便排查。

建议:在守护脚本中启动子脚本时,获取 ScriptExecution 对象并监听 on('exit') 事件,记录退出码和输出,这样可以清晰知道子脚本是正常结束还是异常退出。


2. arguments 传参 / execArgv 接收的方式是否官方兼容、无底层 bug?

这是官方文档明确支持的参数传递方式,长期兼容,可以放心使用。

  • 调用 engines.execScriptFile(path, arg1, arg2, ...) 时,path 之后的所有参数都会作为独立参数传递给子脚本的 arguments 对象。
  • 在子脚本中,通过 engines.myEngine().execArgv 可以获取到一个数组,顺序与调用时传入的参数一致。

文档地址 https://docs.hamibot.com/ (你可以在脚本注释中标注)已经说明了这种用法,且 Hamibot 的脚本引擎底层基于 Rhino,对 argumentsexecArgv 的支持是框架级别的,不会有突然失效的隐患。

注意:由于引擎是 Rhino 1.7.15,建议在传递 JSON 字符串时,确保内容不会破坏 JavaScript 语法。比如尽量使用 JSON.stringify 序列化,子脚本中再用 JSON.parse 还原,避免手动拼接字符串。


3. 手机重启 / Hamibot 重开后,读取 /sdcard/WLmob_AI/ 自定义文件夹是否存在权限拦截?

一般不需要额外权限适配,但存在少数设备因权限回收导致读取失败的可能,加一层主动检查会更稳妥。

  • Hamibot 在安装和使用时,通常会申请并保持 存储 权限,重启后系统自动授予。大多数情况下,/sdcard/ 目录可直接读取。
  • 但有部分手机系统(如小米、OPPO 的某些版本)在电池优化或后台管理中,可能会在重启后重置权限,导致 Hamibot 无法访问存储。此时 files.exists() 会返回 falsefiles.read() 抛出异常。
  • 一个简单有效的防御策略是:在守护脚本首次启动(或每次读取文件前)检查权限,如果权限缺失,则引导用户重新授权。

示例代码(放在守护脚本开头):

// 文档地址 https://docs.hamibot.com/
// 检查存储权限
if (!files.isDir('/sdcard/WLmob_AI/')) {
    // 如果不存在,尝试请求权限
    app.startActivity({
        action: 'android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION',
        packageName: 'com.hamibot',
    });
    sleep(2000);
    // 这里可以再加一次判断,如果依然没有权限,退出脚本并提示用户手动授权
    if (!files.isDir('/sdcard/WLmob_AI/')) {
        toast('请授予Hamibot“所有文件访问权限”后重新运行脚本');
        exit();
    }
}

这样即使权限被回收,也能快速恢复,不会让整个守护脚本崩溃。


技术实现参考

守护脚本(常驻云端)核心逻辑:

// 文档地址 https://docs.hamibot.com/
// 轮询检查任务文件
while (true) {
    var taskFile = '/sdcard/WLmob_AI/task.json';
    if (files.exists(taskFile)) {
        var taskConfig = files.read(taskFile);
        // 读取后删除或重命名,避免重复执行
        files.remove(taskFile);
        // 执行本地业务脚本,传递 JSON 字符串
        var execution = engines.execScriptFile(
            '/sdcard/WLmob_AI/business/wechat/wechat_sales.js',
            taskConfig
        );
        // 监听子脚本退出事件
        execution.on('exit', function(code) {
            // 可以在这里记录日志或处理结果
            console.log('子脚本退出,退出码:' + code);
        });
        // 如果业务脚本是短任务,这里可以适当延时,避免同时启动多个实例
        sleep(1000);
    }
    sleep(3000); // 轮询间隔
}

业务脚本 wechat_sales.js 基本结构:

// 文档地址 https://docs.hamibot.com/
try {
    // 获取传入的参数
    var execArgv = engines.myEngine().execArgv;
    var taskConfig = {};
    if (execArgv && execArgv.length > 0) {
        taskConfig = JSON.parse(execArgv[0]);
    }
    // 执行业务逻辑......
    console.log('任务开始执行,配置:' + JSON.stringify(taskConfig));
    // 你的业务代码
    // 如果是一次性任务,执行完会自动退出,守护脚本会收到 exit 事件
} catch (e) {
    console.error('业务脚本异常:' + e.message);
    // 确保主脚本知道这里失败了,可以通过写入失败日志文件等方式
}

总结
你目前这套架构完全可行,execScriptFile + arguments/execArgv 是稳定且官方支持的方案,比远程 execScript 更适合生产环境。只要做好文件存在性校验、子脚本异常捕获和必要的权限检查,就可以稳定运行,避免反复重构。

ℹ️ 内容由 AI 生成,可能不准确,请注意核实