包规范
本节定义 TOS 7 应用包的正式规范。所有应用必须符合本规范。
应用生命周期
TOS 7 应用遵循明确定义的生命周期:
安装 ──► 配置 ──► 启动 ──► 运行中
│ │ │ │
│ │ │ ├── 停止 ──► 已停止 ──► 启动(重启)
│ │ │
│ │ └── 崩溃 ──► 自动重启(如已配置)
│ │
│ └── 升级 ──► 停止 ──► 安装新版 ──► 迁移 ──► 启动
│
└── 卸载 ──► 停止 ──► 清理 ──► 移除
Deb 应用的生命周期阶段:
| 阶段 | 触发条件 | 脚本/操作 | 预期行为 |
|---|---|---|---|
| 安装前 | dpkg -i | DEBIAN/preinst | 创建用户、检查前置条件、创建目录 |
| 安装 | dpkg -i | 包解压 | 文件按打包规范部署(参见第 8 章);实际在 TOS 7 上的安装路径为 /Volume*/@apps/<appid>/ |
| 安装后 | dpkg -i | DEBIAN/postinst | 设置权限、启用服务、启动服务 |
| 启动 | systemctl start | systemd / init.d | 应用进程启动 |
| 停止 | systemctl stop | systemd / init.d | 应用进程优雅停止 |
| 卸载前 | dpkg --remove | DEBIAN/prerm | 停止服务 |
| 卸载后 | dpkg --remove | DEBIAN/postrm | 清理用户、数据、残留文件 |
| 升级 | dpkg -i(新版本) | prerm → 升级 → postinst | 停止旧版、安装新版、迁移数据、启动 |
Docker 应用的生命周期阶段:
| 阶段 | 触发条件 | 操作 | 预期行为 | 补充说明 |
|---|---|---|---|---|
| 安装 | 应用中心(用户点击「安装」按钮) | 拉取镜像、创建卷 | 镜像可用、数据目录已创建 | 平台自动执行安装流程,开发者无需额外干预 |
| 启动 | 应用中心(用户点击「启动」按钮)/ docker-compose up | 启动容器 | 服务可访问 | 支持用户手动在命令行启动,与平台操作逻辑一致 |
| 停止 | 应用中心(用户点击「停止」按钮)/ docker-compose down | 停止容器 | 服务已停止,数据保留 | 仅停止容器进程,不会删除挂载的数据卷 |
| 升级 | 应用中心(用户点击「更新」按钮,存在新版本) | 拉取新镜像、重建容器 | 零停机或短暂停机 | 建议应用支持平滑升级,避免数据中断 |
| 卸载 | 应用中心(用户点击「卸载」按钮) | 移除容器、可选清理卷 | 所有资源释放 | 用户可选择是否保留数据卷,避免误删数据 |
说明:"应用中心"指TOS系统内置的应用管理界面,用户通过该界面执行的安装/启动/停止/升级/卸载操作,均会触发对应生命周期流程。
版本号规范
TOS 7 遵循 语义化版本号(SemVer):
主版本号.次版本号.修订号
主版本号:不兼容的 API 变更
次版本号:向后兼容的新功能
修订号:向后兼容的问题修复
规则:
- 每次提交的版本号必须严格大于前一版本
- 禁止版本降级
- 版本号必须在 config.ini 的
version、DEBIAN/control 的Version、app.lang 的version之间保持一致 - 平台在提交时会校验版本一致性
- 版本号最大长度:20 个字符。超出将被驳回。
- 版本号允许字符:仅限数字(
0-9)和点(.)。示例:"1.2.3" - 预发布/测试版必须使用 config.ini 中的
"beta": true字段,而非版本号后缀。
Beta 版本管理说明:
- 平台不支持版本号后缀(如
-beta、-rc、-alpha) - 多个测试版通过递增修订号区分:
- 第一个测试版 →
"version": "1.0.0"+"beta": true - 第二个测试版 →
"version": "1.0.1"+"beta": true - 第三个正式版 →
"version": "1.0.2"+"beta": false
- 第一个测试版 →
- 正式版发布:设置
"beta": false,版本号按正常规则递增 - 版本回滚:平台不支持版本号"变小"的回滚。如需回滚,需在开发者平台提交回滚申请,由平台操作将应用回滚至上一个稳定版本
- 详见附录 N Beta 版应用管理
Release 资源命名规范
将应用包上传至 GitHub/Gitee Releases 时,包文件必须遵循以下命名规范。
版本号不包含在包文件名中。版本通过创建 Release 时的 Release 标签/版本号指定。平台将从 Release 元数据中读取版本并与 config.ini 中的 version 字段进行比对校验。
| 应用类型 | 包格式 | 命名规范 | 示例 |
|---|---|---|---|
| Deb(单包模式) | .deb 文件 | <app_id>_<platform>.deb | myapp_x86_64.deb |
| Deb(双包模式) | .tar.gz 压缩包 | <app_id>_<platform>.tar.gz | myapp_x86_64.tar.gz |
| Docker 应用 | .tar.gz 压缩包 | <app_id>.tar.gz | myapp.tar.gz |
字段定义:
<app_id>:必须与config.ini中的id字段完全一致<platform>:必须与config.ini中的platform字段完全一致(x86_64或aarch64)
Release 标签要求:
- Release 标签/版本号必须与
config.ini中的version字段完全一致(格式:xx.yy.zzz)。 - 示例:若
config.ini.version = "1.0.0",则 Release 标签必须为v1.0.0或1.0.0。 - Release 版本与
config.ini.version不一致将导致自动驳回。
升级
Deb 应用升级:
- 升级时
preinst收到$1 = "upgrade"参数 postinst收到$1 = "configure"参数,$2为旧版本号- 使用
$2检测旧版本并执行数据迁移 - 升级过程中绝不删除用户数据,仅修改配置格式或迁移数据结构
- 用户将持久化业务数据存储在
/Volume*/<appid>/共享文件夹中,该文件夹由应用通过ter_share_add创建。平台在应用升级或重装时不会删除或覆盖此共享文件夹中的用户数据 - 运行时数据(缓存、临时文件)存储在
/Volume*/@apps/<appid>/data/中,可安全重新生成 - 建议不要将数据存储在
/etc、/var、/usr/bin等系统公共目录,此类目录可能因系统更新或应用升级被覆盖,导致数据丢失
# 示例:postinst 中包含迁移逻辑
case "$1" in
configure)
if [ -n "$2" ]; then
# 从版本 $2 升级
if dpkg --compare-versions "$2" lt "2.0.0"; then
# 将 v1.x 配置格式迁移到 v2.x
/usr/local/<appid>/bin/migrate.sh "$2"
fi
else
# 全新安装
echo "全新安装"
fi
;;
esac
Docker 应用升级:
- 拉取新的镜像标签
- 使用现有卷挂载重建容器
- 通过持久化卷在升级间保留数据
- 如有需要,在应用入口脚本中包含迁移逻辑
兼容性矩阵
| TOS 版本 | 基础系统 | glibc | Python3 | Docker | Node.js |
|---|---|---|---|---|---|
| TOS 7.0 | Ubuntu 22.04 兼容 | 2.35 | 3.10 | 20.10+ | 18.x |
| TOS 7.x | Ubuntu 22.04 兼容 | 2.35 | 3.10 | 20.10+(或更高) | 18.x(或更高) |
Node.js 版本仅供 Docker 容器内使用参考,Deb 应用不可直接依赖。
应用必须通过 config.ini 中的 low_version 声明最低 TOS 版本要求。平台将自动过滤不兼容的设备。
TOS 7.x 小版本兼容性: TOS 7.x 系列小版本(含 7.1 及以上)将保持核心依赖(glibc/Python3/Docker/Node.js)的 ABI/API 兼容性,兼容于 Ubuntu 22.04 的根文件系统。为 TOS 7.0 开发的应用无需额外适配即可运行。
TOS 7 小版本兼容性:
low_version字段必须指定所需的最低 TOS 版本- 提交更新时,请在最新的 TOS 7 小版本上测试
大小写敏感规范
TOS 采用兼容 Ubuntu Linux 的根文件系统,文件系统严格区分大小写。所有应用必须遵循以下规则:
| 要素 | 规则 |
|---|---|
| 文件名 | 严格匹配大小写。config.ini ≠ Config.ini ≠ CONFIG.INI |
| 目录名 | 严格匹配大小写。/images/icons/ ≠ /Images/Icons/ |
| config.ini 键名 | 所有键名小写。"version" 正确,"Version" 错误 |
应用 ID(id) | 严格匹配大小写。MyApp ≠ myapp 。创建后不可修改 |
| Systemd 服务名 | 必须严格匹配,区分大小写 |
在单个应用包中使用同一文件或目录的大小写变体。这会导致 Linux 上出现"找不到文件"和"服务启动失败"错误。
跨平台换行符规范(CRLF to LF)
所有在 TOS 系统(Linux 环境)中运行的脚本和配置文件,必须使用 LF(\n)作为换行符,禁止使用 Windows 默认的 CRLF(\r\n)换行符。
问题影响
- 脚本执行报错
bad interpreter: No such file or directory - 配置文件解析失败(如 systemd 服务文件、Nginx 配置)
- 解释器路径被错误识别为
/bin/bash\r等不存在的二进制
强制要求
- 所有
.sh/.py/.ini/.lang/.service/.conf文件,提交前必须转为 LF 换行 - Deb 包构建脚本中,必须加入自动转换逻辑,避免构建过程中引入 CRLF
推荐修复方案
方案 1:在构建脚本中自动转换(推荐)
import os
def convert_crlf_to_lf(file_path):
with open(file_path, "rb") as f:
content = f.read()
content = content.replace(b"\r\n", b"\n")
with open(file_path, "wb") as f:
f.write(content)
# 打包前,遍历所有需要转换的文件
for root, _, files in os.walk("your_app_source/"):
for name in files:
if name.endswith((".sh", ".py", ".ini", ".lang", ".service", ".conf")):
convert_crlf_to_lf(os.path.join(root, name))
方案 2:本地开发工具配置
- VS Code:右下角状态栏点击
CRLF,切换为LF后保存 - Git 全局配置(避免后续文件自动转为 CRLF):
git config --global core.autocrlf input