你好,我是Hamibot开发者,遇到一个严重的脚本路径问题,麻烦协助解答:
【设备与环境】
- 手机:小米 Note 13 / 小米 Note 9 Pro
- 系统:MIUI 14(Android 13)
- Hamibot版本:1.6.7
- 脚本位置:所有脚本(守护脚本 wla_daemon.js、业务脚本 douyin_follow.js)均在Hamibot同一账号、同一分组内,列表可见,可手动运行。
【问题现象】
- 守护脚本 wla_daemon.js 用 engines.execScriptFile() 调用同目录下的 douyin_follow.js,日志直接报:
FileNotFoundException: 没有那个文件或目录 - 两个脚本都在Hamibot内部,文件名完全正确(无空格、大小写一致),手动运行正常。
- 但守护脚本就是“找不到”同目录脚本,必须把脚本放到 /sdcard/ 根目录才能被execScriptFile找到。
【关键日志】
(把你完整日志贴这里,尤其报错那几行)
【我的疑问】
- Hamibot 内部脚本的真实物理路径是什么?为什么同目录脚本execScriptFile找不到?
- engines.execScriptFile() 到底支持哪些路径?是否存在“虚拟目录/分组隔离”导致的路径不一致?
- 官方推荐:在Hamibot内部,通过脚本名直接调用的正确API是什么?(我查到有execScriptByName,但不确定是否官方推荐、是否稳定)
【我的诉求】请官方明确:
- 同账号/同分组内,脚本之间互相调用的标准、稳定写法
- 避免FileNotFoundException的正确路径配置或API用法

标题:后台守护脚本用 engines.execScript 调用子脚本,返回成功但子脚本完全不执行、不打印日志
内容:
我在做一个 “守护脚本 + 业务脚本” 的分离架构:
守护脚本(wla_daemon)在 Hamibot 前台正常运行,无障碍、后台弹出、自启动、省电白名单全部开了。
守护脚本通过:
javascript
运行
let engine = engines.execScript("douyin_follow.js", {
execArgv: { msgList: [], keywordRule: {} }
});
调用抖音业务脚本,返回值正常、不报任何错。
但 douyin_follow.js 完全不执行:
没有任何日志输出(连最开头的 console.show ()、log () 都不打印)
抖音完全不被拉起
子脚本像是 “被静默拦截” 了
单独直接运行 douyin_follow.js 是可以正常跑、正常拉起抖音、正常打印日志的。
我的环境:
手机:小米 Note 13 / MIUI 14
Hamibot:最新版
无障碍、后台弹出、悬浮窗、自启动、省电白名单全部已开启
想问:
engines.execScript 在前台守护脚本里调用另一个脚本,是否有什么限制?
为什么 execScript 返回成功,但子脚本完全不执行、不输出日志?
官方推荐的 “守护脚本调度业务脚本” 正确写法是什么?
回答
你遇到的 FileNotFoundException 是 Hamibot 脚本管理中非常典型的路径认知差异问题。核心原因在于 engines.execScriptFile() 的设计定位与 Hamibot 内部脚本的存储机制不匹配。下面为你逐一解答并提供标准写法。
1. Hamibot 内部脚本的真实物理路径是什么?为什么同目录调用会报错?
Hamibot 列表中的脚本并不以普通文件形式暴露在公共存储中。它们由 Hamibot 应用沙盒与云端同步机制统一管理,存储在应用私有目录或加密缓存中,路径是动态生成且受 Android 系统严格限制的。engines.execScriptFile() 底层依赖 java.io.File,只能识别 Android 文件系统的绝对物理路径。当你传入相对路径或脚本名时,引擎会在当前运行工作目录中查找文件,无法命中 Hamibot 内部管理的脚本,因此直接抛出 FileNotFoundException。
2. engines.execScriptFile() 支持哪些路径?是否存在分组隔离?
- 该 API 仅支持设备存储的绝对路径,例如
/sdcard/Scripts/douyin_follow.js或通过files.path('./douyin_follow.js')转换后的完整路径。 - Hamibot 的“账号/分组”是云端同步与管理界面的逻辑概念,并非文件系统的真实目录。脚本在本地没有按分组建立文件夹,因此不存在“同目录”的文件系统映射,也不支持通过相对路径互相调用。
3. 官方推荐的内部脚本调用 API 是什么?
在 Hamibot 内部互相调用脚本,标准且稳定的 API 是 engines.execScript(name[, config])。该接口专门用于运行 Hamibot 脚本列表中的脚本,引擎会自动通过脚本名称在本地缓存索引中定位并执行,完全避开物理路径问题。你提到的 execScriptByName 并非官方标准 API,请直接使用 engines.execScript()。
✅ 同账号/分组内脚本互相调用的标准写法
// 文档地址 https://docs.hamibot.com/
// 守护脚本 wla_daemon.js 中调用业务脚本
var targetScriptName = 'douyin_follow.js'; // 必须与 Hamibot 列表中的名称完全一致(含后缀)
var config = {
loopTimes: 1,
interval: 0
};
var execution = engines.execScript(targetScriptName, config);
if (execution) {
console.log('成功启动脚本: ' + targetScriptName);
} else {
console.error('启动失败:未找到脚本,请检查名称是否完全匹配或脚本是否已同步到本地');
}
📌 关键注意事项与最佳实践
- 名称严格匹配:
engines.execScript()依赖脚本在 Hamibot 列表中的完整名称,区分大小写,必须包含.js后缀。 - 同步状态:被调用的脚本必须在 Hamibot 客户端中可见(已同步到本地)。若脚本仅存在于云端未拉取,首次调用可能失败,建议在 Hamibot 界面手动运行一次或确保网络同步完成。
- 独立运行环境:通过
engines.execScript()启动的脚本会在新的独立环境中运行,不共享父脚本的全局变量。若需传递参数,推荐使用storage模块或本地文件读写。 - 权限检查:若子脚本启动后立即提示“运行结束”,请进入手机设置确认已开启 Hamibot 的无障碍服务,并授予“后台弹出界面”、“显示悬浮窗”及“自启动/后台启动”权限(MIUI 系统对后台限制较严,需手动放行)。
- 引擎兼容性:Hamibot 使用 Rhino 1.7.15 引擎,示例已避免箭头函数与默认参数,确保在 Android 13/MIUI 14 环境下稳定执行。
使用 engines.execScript() 替换 execScriptFile() 即可彻底解决路径找不到问题,并符合 Hamibot 云端脚本管理的架构设计。如有参数传递或跨脚本状态同步的具体场景,可提供细节,我会为你补充对应方案。
你遇到的“返回成功但子脚本静默不执行”是 MIUI 14 后台限制与 Hamibot 引擎特性叠加导致的典型现象。engines.execScript 返回对象仅表示引擎创建与任务派发成功,不代表子脚本已完整运行。下面逐条解答并提供标准调度方案。
1. engines.execScript 在守护脚本中调用是否有限制?
引擎层面没有限制,支持任意脚本互相调用。但受 Android 10+ 及 MIUI 14 系统策略影响,后台上下文启动的脚本在创建 UI、悬浮窗或拉起其他应用时会被严格拦截。若子脚本包含 console.show() 或强依赖前台权限的操作,系统会直接终止该引擎进程,表现为“静默退出”。
2. 为什么返回成功但子脚本不执行、不打印日志?
- 配置参数写法错误:
engines.execScript的 config 对象不支持execArgv字段。传入无效键值会被忽略,但子脚本若通过engines.myEngine().execArgv读取参数会得到undefined,若开头有强依赖逻辑会直接抛出异常退出。 console.show()导致静默崩溃:后台调度的脚本调用console.show()在 MIUI 上极大概率失败。若未包裹try-catch,脚本会在首行直接崩溃,后续log()与抖音拉起逻辑均不会执行。- 日志不可见误区:后台引擎的
log()输出默认写入 Hamibot 内部日志缓冲,不会自动弹出控制台。你看到的“不打印日志”通常是控制台创建失败,而非脚本未运行。 - 应用拉起拦截:MIUI 的“后台弹出界面”与“链式启动”限制会拦截
launchApp(),需配合包名启动或确保权限完整放行。
3. 官方推荐的“守护脚本调度业务脚本”标准写法
使用 engines.execScript() 配合 storages 传参,移除子脚本中的 console.show(),并增加异常捕获与 MIUI 兼容启动逻辑。
守护脚本(wla_daemon.js)
// 文档地址 https://docs.hamibot.com/
var storage = storages.create('wla_daemon');
storage.put('msgList', []);
storage.put('keywordRule', {});
var targetName = 'douyin_follow.js';
var execution = engines.execScript(targetName, {
loopTimes: 1,
interval: 0
});
if (execution) {
log('已派发任务: ' + targetName);
} else {
log('任务派发失败,请检查脚本名称或同步状态');
}
业务脚本(douyin_follow.js)
// 文档地址 https://docs.hamibot.com/
try {
// 后台调度脚本严禁使用 console.show(),MIUI 会拦截悬浮窗创建导致静默崩溃
// 所有日志请通过 Hamibot 客户端「运行日志」查看
log('douyin_follow.js 开始执行');
var storage = storages.create('wla_daemon');
var msgList = storage.get('msgList', []);
var keywordRule = storage.get('keywordRule', {});
log('读取参数成功: ' + JSON.stringify(keywordRule));
// MIUI 兼容的抖音拉起方式
var launched = launchApp('抖音');
if (!launched) {
log('名称拉起失败,尝试包名启动');
app.startActivity({
packageName: 'com.ss.android.ugc.aweme',
className: 'com.ss.android.ugc.aweme.main.MainActivity'
});
}
log('抖音已拉起,执行业务逻辑');
// 你的业务代码...
} catch (e) {
log('douyin_follow.js 运行异常: ' + e);
}
📌 关键排查与最佳实践
- 彻底移除
console.show():守护/后台调度的子脚本绝对不要使用该方法。MIUI 会直接拦截导致脚本首行崩溃。调试期可用files.write('/sdcard/hamibot_debug.log', new Date() + ' started\n', true);验证脚本是否真正进入执行阶段。 - 正确传参方式:
engines.execScript不支持execArgv配置。跨脚本数据传递统一使用storages模块或本地文件,稳定且兼容所有 Android 版本。 - MIUI 14 权限复核:设置 → 应用设置 → Hamibot → 权限管理,确保开启:
后台弹出界面、显示悬浮窗、自启动、省电策略-无限制。开发者选项中关闭“暂停执行后台应用”。 - 日志查看路径:子脚本的
log()输出不会实时弹窗,请打开 Hamibot 客户端 → 底部「我的」→ 「运行日志」查看完整输出。 - 引擎兼容性:示例已适配 Rhino 1.7.15,避免箭头函数与默认参数,确保在 Android 13 环境下稳定执行。
按上述结构替换后,子脚本即可正常被调度并执行。若 /sdcard/hamibot_debug.log 仍未生成,请检查 Hamibot 列表中 douyin_follow.js 的名称是否包含隐藏空格或特殊字符,并确保脚本已点击“同步”至本地。需要进一步定位可提供日志文件生成结果或 Hamibot 运行日志截图。