一次性脚本
一次性脚本是一个由 KernelSU 管理器运行一次、而不是安装的 ZIP。它的打包方式与模块相同,但不会在设备上留下任何东西:管理器把 ZIP 解压到私有目录,询问它声明的参数,展示 action.sh 的源码,然后在 root shell 中运行它。它适合解锁隐藏设置、导出日志之类的任务;需要在开机时运行或修改系统分区的功能应当做成模块。
包结构
<id>-<version>.zip
├── module.prop # 常规 module.prop 字段 + oneshot=true
├── action.sh # 必需:管理器运行的脚本
├── params.json # 可选:运行前询问的参数
├── customize.sh # 可选:仅在 ZIP 被当作模块安装时使用
└── other files # 脚本通过 $MODPATH 读取的数据module.prop 的字段与模块相同,另外增加 oneshot:
id=example_script
name=Example Script
version=v1
versionCode=1
author=Alice
description=Does a thing once
oneshot=trueoneshot 的解析方式与 metamodule 相同:去掉首尾空白后为 1 或 true(不区分大小写)即生效;其他值或没有 oneshot 行都表示普通模块。
不要包含 post-fs-data.sh、service.sh、system.prop、sepolicy.rule 或 system/ 目录等模块专用文件:一次性运行永远不会用到它们。一次性脚本不能是元模块。
运行脚本
有两种方式运行一次性脚本:
- 从模块仓库运行:KernelSU Modules 仓库中
kind: script的条目会显示「脚本」标签,并用 运行 按钮代替 安装。下载的文件会按仓库记录的大小和 SHA-256 校验,且module.prop中的id必须与登记的一致。 - 从本地 ZIP 运行:从存储中选择单个 ZIP(或从其他应用打开 ZIP)时,如果它的
module.prop含有oneshot=true,将打开运行页面而不是安装器。页面上还提供 仍作为模块安装。
运行前,管理器会检查 module.prop 声明了 oneshot 且 id 合法、ZIP 根目录存在 action.sh,然后解压 ZIP。绝对路径、..、符号链接和特殊文件都会被拒绝,解压内容限制为 64 MiB、4096 个条目。
运行页面展示参数表单、action.sh 源码和本设备上的上一次运行记录。确认后,管理器在全局挂载命名空间中新开一个 root shell 运行脚本,与模块的 Action 按钮相同:
cd <dir> && <env> /data/adb/ksu/bin/busybox sh ./action.sh </dev/null输出的展示方式与 Action 输出相同,并且可以保存。运行结束后解压目录会被删除。管理器只记录上一次运行(版本和退出码);没有已安装状态,也没有更新检查。
环境变量
| 变量 | 值 |
|---|---|
ASH_STANDALONE | 1 |
KSU | true |
KSU_VER、KSU_VER_CODE、KSU_KERNEL_VER_CODE | KernelSU 版本,与模块相同 |
KSU_LATE_LOAD | 仅在 late-load 模式下为 1 |
KSU_MODULE | 脚本 ID |
KSU_ONESHOT | 1,用于区分一次性运行和已安装模块的 Action 按钮 |
MODPATH | 解压目录;从这里读取你的数据文件 |
PATH | $PATH:/data/adb/ksu/bin |
KSU_PARAM_<KEY> | 每个参数一个,见 params.json |
标准输入是 /dev/null,脚本无法交互式读取输入;请改用参数。
退出码
| 退出码 | 含义 |
|---|---|
0 | 成功。 |
2 | 不适用于此设备;以提示而非失败的形式展示。 |
| 其他 | 失败。 |
params.json
params.json 是可选的,位于 ZIP 根目录,为 UTF-8 JSON,最大 64 KiB。管理器据此生成表单,并把每个值以 KSU_PARAM_<KEY> 传给 action.sh。
{
"schemaVersion": 1,
"params": [
{
"key": "ENABLE_FASTBOOT",
"type": "bool",
"label": "Also enable fastboot",
"description": "Optional longer help text",
"default": true
},
{ "key": "MODE", "type": "enum", "label": "Mode", "default": "a",
"options": [ { "value": "a", "label": "A" }, { "value": "b" } ] },
{ "key": "NAME", "type": "string", "label": "Name", "default": "", "maxLength": 64,
"required": false },
{ "key": "COUNT", "type": "int", "label": "Count", "default": 1, "min": 0, "max": 10 }
]
}| 字段 | 规则 |
|---|---|
schemaVersion | 必须为 1。 |
params | 最多 16 个参数。 |
key | ^[A-Z][A-Z0-9_]{0,31}$,不可重复。值以 KSU_PARAM_<key> 传给脚本。 |
type | bool、enum、string 或 int。 |
label | 必需,1–200 个字符。按原样显示(单语言)。 |
description | 可选,规则同 label。 |
各类型:
| 类型 | 字段 | 传入形式 |
|---|---|---|
bool | default:true / false(默认 false)。 | true / false |
enum | options:1–32 项 {value, label?};value 匹配 ^[A-Za-z0-9._-]{1,64}$ 且不可重复。default 必须是其中一个值(默认为第一项)。 | 选项的 value |
string | default(默认 "")、maxLength 1–1024(默认 256)、required(默认 false;非必填时允许空值)。值不能包含 NUL 或换行。 | 原样 |
int | 可选的 min / max 和 default(默认为 min,没有 min 时为 0);32 位有符号整数。 | 十进制 |
每个参数的 default 都必须满足自身的约束。params.json 无效时,管理器会拒绝运行该脚本。
注意
string 类型的值没有格式校验。每个值都以单引号传入,所以启动 action.sh 的 shell 不会展开它,但 action.sh 仍需自行校验,并在使用时加引号。
示例
#!/system/bin/sh
# action.sh
MODPATH=${MODPATH:-${0%/*}}
if [ "$(getprop ro.miui.ui.version.name)" = "" ]; then
echo "Not a MIUI device"
exit 2
fi
echo "Mode: ${KSU_PARAM_MODE:-a}"
if [ "$KSU_PARAM_ENABLE_FASTBOOT" = "true" ]; then
sh "$MODPATH/fastboot.sh" || exit 1
fi
echo "Done"兼容旧版管理器
不支持一次性脚本的管理器会把 ZIP 当作普通模块安装,其 Action 按钮会运行 action.sh。请保证 action.sh 在这种情况下也能工作:此时 KSU_ONESHOT、MODPATH 和 KSU_PARAM_* 都未设置,工作目录为模块目录。像上面的示例一样回退到默认值:
MODPATH=${MODPATH:-${0%/*}}
MODE=${KSU_PARAM_MODE:-a}发布
要在 KernelSU Modules 上发布一次性脚本,请在 module.yaml 中设置 kind: script。仓库规则见 Script entries。