Skip to main content
fnos-fpk-dev Use when developing fnOS FPK packages, writing lifecycle scripts, or configuring manifest, privilege, resource, wizard, and desktop UI files. Covers package structure, environment variables, packaging, and common platform constraints.
Jump to install Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/jianyun8023/my-skills --skill fnos-fpk-devThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... More from this repository Use when the user asks to check disk status, report on hard disk health, temperature, or SMART data, or when performing routine server maintenance.
Use when containerizing VPN clients into Docker, supporting both GUI (VNC) and CLI (Web management) modes with danted SOCKS5 proxy
Use when editing `.alloy` files, configuring Grafana Alloy pipelines, or debugging log collection and relabeling behavior. Covers HCL syntax, common Loki/Prometheus components, processing stages, Docker discovery, and FnOS-specific patterns.
name fnos-fpk-dev description Use when developing fnOS FPK packages, writing lifecycle scripts, or configuring manifest, privilege, resource, wizard, and desktop UI files. Covers package structure, environment variables, packaging, and common platform constraints.
飞牛 fnOS FPK 应用开发
适用场景
新建 fnOS FPK 应用包
编写或调整 manifest、cmd/ 生命周期脚本、wizard/、config/privilege、config/resource
为 FPK 应用添加桌面图标 Web UI
排查打包结构、环境变量或脚本退出码问题
不适用
非 fnOS / FPK 平台的 Docker、Kubernetes 或通用 Linux 打包任务
只调试应用业务代码,不涉及 FPK 目录结构、生命周期或 manifest
需要官方 root 权限发布资格、签名或上架审核流程细节时
应用目录结构
FPK 安装后的标准目录结构:
/var/apps/[appname]
├── cmd/ # 生命周期脚本(必须)
│ ├── main # 启停和状态检查
│ ├── install_init # 安装前
│ ├── install_callback # 安装后
│ ├── uninstall_init # 卸载前
│ ├── uninstall_callback # 卸载后
│ ├── upgrade_init # 更新前
│ ├── upgrade_callback # 更新后
│ ├── config_init # 配置前
│ └── config_callback # 配置后
├── config/
│ ├── privilege # 权限声明(JSON)
│ └── resource # 资源/能力声明(JSON)
├── wizard/
│ ├── install # 安装向导(JSON)
│ ├── uninstall # 卸载向导(JSON)
│ ├── upgrade # 更新向导(JSON)
│ └── config # 配置向导(JSON)
├── manifest # 应用身份信息(key=value)
├── ICON.PNG # 小图标 64x64
├── ICON_256.PNG # 大图标 256x256
├── LICENSE # 隐私协议(可选)
├── etc -> /vol[x]/@appconf/[appname] # 静态配置
├── home -> /vol[x]/@apphome/[appname] # 用户数据
├── target -> /vol[x]/@appcenter/[appname] # 可执行文件(TRIM_APPDEST)
│ └── ui/ # 桌面图标 Web UI 配置(可选,由 desktop_uidir 指定)
│ ├── images/
│ │ ├── icon-64.png # 64x64 桌面图标
│ │ └── icon-256.png # 256x256 桌面图标
│ └── config # 入口配置文件(JSON)
├── tmp -> /vol[x]/@apptemp/[appname] # 临时文件(TRIM_PKGTMP)
├── var -> /vol[x]/@appdata/[appname] # 运行时数据(TRIM_PKGVAR)
├── meta -> /vol[x]/@appmeta/[appname] # 应用元数据(TRIM_PKGMETA)
└── shares/ # 数据共享目录(由 resource 定义)
开发目录与安装目录映射 开发时 安装后 环境变量 说明 app/target/TRIM_APPDEST可执行文件、UI 资源 cmd/cmd/— 生命周期脚本 config/config/— privilege + resource wizard/wizard/— 向导定义 manifestmanifest— 应用元信息 ICON.PNGICON.PNG— 小图标 64x64 — var/TRIM_PKGVAR运行时数据(系统创建) — etc/TRIM_PKGETC静态配置(系统创建) — home/TRIM_PKGHOME用户数据(系统创建) — tmp/TRIM_PKGTMP临时文件(系统创建) — meta/TRIM_PKGMETA元数据(系统创建) — shares/— 共享目录(由 resource 定义)
关键 :app/ 目录对应安装后的 target(TRIM_APPDEST),桌面 UI 配置必须放在 app/ui/ 下。
核心系统环境变量
常用路径变量 变量 说明 TRIM_APPDEST应用可执行文件目录(target) TRIM_PKGVAR运行时数据目录(var) TRIM_PKGETC静态配置目录(etc) TRIM_PKGHOME用户数据目录(home) TRIM_PKGTMP临时文件目录(tmp)
常用信息变量 变量 说明 TRIM_APPNAME应用名称(来自 manifest appname) TRIM_APPVER应用版本号(来自 manifest version) TRIM_OLD_APPVER升级前的版本号(仅在 upgrade 脚本中可用) TRIM_SERVICE_PORTmanifest 中声明的服务端口 TRIM_USERNAME / TRIM_GROUPNAME应用专用用户名/组名 TRIM_RUN_USERNAME实际运行用户(root 或 package 用户) TRIM_TEMP_LOGFILE系统日志文件路径(写入错误信息供前端展示) wizard_*向导表单字段值(仅在对应 callback 脚本中可用)
cmd/main 脚本(必须) #!/bin/bash
PID_FILE="${TRIM_PKGVAR} /app.pid"
case $1 in
start)
exit 0
;;
stop)
exit 0
;;
status)
if [ -f "$PID_FILE " ]; then
pid=$(cat "$PID_FILE " | tr -d '[:space:]' )
if [ -n "$pid " ] && kill -0 "$pid " 2>/dev/null; then
exit 0
fi
rm -f "$PID_FILE "
fi
exit 3
;;
*)
exit 1
;;
esac
status 返回 exit 0 = 运行中,exit 3 = 未运行
错误时写入 $TRIM_TEMP_LOGFILE 后 exit 1,不要直接 echo
系统会定期轮询 status 检查健康状态
manifest 文件 key=value 格式(等号前后无空格),定义应用基本信息:
appname =com.example.myapp
version =1.0 .0
display_name =我的应用
desc =应用描述,支持HTML
platform =x86
source =thirdparty
maintainer =开发者名称
distributor =发布者名称
service_port =8080
checkport =true
os_min_version =0.9 .0
install_dep_apps =mariaDB:redis
desktop_uidir =ui
desktop_applaunchname =com.example.myapp.main
ctl_stop =true
install_type=
changelog =修复已知问题
arch 已废弃,使用 platform 替代,不支持多个值填写。
desktop_applaunchname 必须与 app/ui/config 中 .url 下定义的入口 key 一致。
ctl_stop=false 时隐藏启停按钮和运行状态,适用于无进程应用。
install_type=root 时安装到系统分区 /usr/local/apps/@appcenter/,为空时用户选择 /vol${x}/@appcenter/。
install_dep_apps 格式:app1>2.2.2:app2:app3,> 表示最低版本要求。
config/privilege(权限声明) {
"defaults" : {
"run-as" : "package"
} ,
"username" : "myapp" ,
"groupname" : "myapp"
}
run-as: "package" — 应用用户运行(推荐,安全)
run-as: "root" — root 权限运行(仅官方合作开发者可发布)
未指定 username / groupname 时默认使用 manifest 中的 appname
完整说明(含 folder-permission)见 reference.md
config/resource(资源声明) 支持三种资源类型,常用的是 data-share:
{
"data-share" : {
"shares" : [
{
"name" : "myapp-data" ,
"permission" : {
"rw" : [ "myapp" ]
}
}
]
}
}
permission 数组中填写 privilege 中定义的 username(未定义则为 manifest appname)
声明的共享目录自动创建在 shares/ 下
权限类型:rw(读写)、ro(只读)
其他资源类型(usr-local-linker、docker-project)见 reference.md
wizard(用户向导) [
{
"stepTitle" : "步骤标题" ,
"items" : [
{ "type" : "text|password|radio|checkbox|select|switch|tips" , ... }
]
}
]
表单项类型速查 类型 用途 关键字段 text文本输入 field, label, initValue, rules password密码输入 field, label, rules radio单选 field, label, options, initValue checkbox多选 field, label, options, initValue select下拉选择 field, label, options, initValue switch开关 field, label, initValue(字符串 "true" / "false") tips提示文本 helpText(支持HTML)
验证规则 { "required" : true , "message" : "必填提示" }
{ "min" : 3 , "max" : 20 , "message" : "长度限制" }
{ "len" : 6 , "message" : "精确长度" }
{ "pattern" : "^[a-zA-Z0-9]+$" , "message" : "正则验证" }
获取向导输入 向导 field 字段名直接作为环境变量名,在对应 callback 脚本中读取:
LOKI_URL="${wizard_loki_url:-默认值} "
桌面图标配置(Desktop UI) 为应用添加 fnOS 桌面图标,点击后在浏览器中打开应用 Web UI。
开发时目录结构 app/
└── ui/ # 对应 manifest 的 desktop_uidir = ui
├── images/
│ ├── icon-64.png # 64x64 桌面图标
│ └── icon-256.png # 256x256 桌面图标
└── config # 入口配置文件
重要 :app/ 目录 = 安装后的 target(TRIM_APPDEST)。ui/ 必须放在 app/ 下,否则 fnpack 打包时会报 no such file or directory 错误。
manifest 必填字段 desktop_uidir =ui
desktop_applaunchname =com.example.myapp.main
app/ui/config 格式 入口定义在 .url key 下,key 名必须以 appname 为前缀 :
{
".url" : {
"com.example.myapp.main" : {
"title" : "我的应用" ,
"icon" : "images/icon-{0}.png" ,
"type" : "url" ,
"protocol" : "http" ,
"port" : "8080" ,
"url" : "/" ,
"allUsers" : true
}
}
}
config 字段说明 字段 类型 说明 titlestring 桌面图标显示名称 iconstring 图标路径(相对于 ui 目录),{0} 为尺寸占位符(系统自动替换为 64/256) typestring 入口方式:url(新标签页打开)/ iframe(内嵌页面) protocolstring 访问协议:http / https portstring 应用端口(字符串类型),与 manifest service_port 一致 urlstring 应用访问路径(相对路径,如 /、/admin) allUsersboolean 是否所有用户可见,false 则仅管理员可见
关键规则
图标 {0} 是尺寸占位符,系统自动替换为 64/256,必须提供两个尺寸文件
.url 下的 key 名必须以 manifest appname 为前缀
desktop_applaunchname 指定默认入口(应用中心"打开"按钮使用)
port 是字符串类型 ,应与 manifest service_port 一致
协议注意事项 fnOS 桌面点击图标时,URL 拼接逻辑:{protocol}://{当前浏览器hostname}:{port}{url}
模式 config 配置 适用场景 直连(HTTP + IP) "protocol": "http", "port": "8080"局域网直接访问 反代(HTTPS + 域名) 不声明 port,由 fnOS Nginx 反代转发 通过域名/HTTPS 访问
注意 :HTTPS 页面中声明 protocol: "http" 会导致协议降级和端口不可达。完整的协议适配说明和多入口配置见 reference.md 。
生命周期脚本流程
安装:install_init → 解压文件 → install_callback
卸载:uninstall_init → 删除文件 → uninstall_callback
更新:upgrade_init → 替换文件 → upgrade_callback
配置:config_init → 更新环境变量 → config_callback 卸载保留 var 和 shares 目录(保护用户数据)。
错误处理(V1.1.8+) 脚本中遇到错误时,写入 TRIM_TEMP_LOGFILE 后 exit 1:
if [ ! -f "$TRIM_PKGETC /config.conf" ]; then
echo "配置文件不存在,应用启动失败!" > "${TRIM_TEMP_LOGFILE} "
exit 1
fi
系统会将内容以 Dialog 对话框形式展示给用户。
打包工具 fnpack 使用 fnpack 命令行工具创建和打包 FPK 应用:
fnpack create myapp
fnpack pack [项目目录]
Bash 脚本安全实践
变量加双引号 :"$TRIM_PKGVAR" 而非 $TRIM_PKGVAR,防止路径含空格时出错
错误写入日志 :遇到错误必须写入 "${TRIM_TEMP_LOGFILE}",不要直接 echo 到 stdout
明确退出码 :成功 exit 0,失败 exit 1,status 未运行 exit 3
用 $TRIM_APPNAME 构建路径 :不要硬编码 /var/apps/com.example.myapp,用 /var/apps/${TRIM_APPNAME}
heredoc 生成 JSON 时注意转义 :用户输入的特殊字符(引号、反斜杠)可能破坏 JSON 格式,建议在 callback 中校验
调试技巧
模拟环境变量 :本地测试脚本时,手动 export TRIM_PKGVAR=/tmp/test-var 等模拟环境
查看错误日志 :脚本失败后查看 $TRIM_TEMP_LOGFILE 中写入的内容
验证打包内容 :fnpack pack 生成的 .fpk 实质是压缩包,可解压检查文件结构是否正确
检查脚本权限 :常见问题是脚本缺少执行权限,确保 chmod +x cmd/*
Docker 应用调试 :在 fnOS 终端中手动执行 docker compose 命令排查容器启动失败
开发检查清单
详细参考
常见错误 错误做法 正确做法 把 ui/ 放在项目根目录而不是 app/ui/ 始终让桌面 UI 跟随 app/ -> target/ 映射 cmd/main status 返回 1 代表未运行未运行应返回 exit 3 直接 echo 报错到 stdout 写入 ${TRIM_TEMP_LOGFILE} 再 exit 1 manifest 使用带空格的 key = value使用严格的 key=value 格式 硬编码 /var/apps/com.example.myapp 之类路径 优先使用 TRIM_APPDEST、TRIM_PKGVAR 等环境变量 打包前不检查脚本权限和目录结构 先 chmod +x cmd/*,再用 fnpack pack 验证内容
Related occupations SOC
Based on SOC occupation classification