AUR 自动构建脚本设计与改进

最近折腾了一套 AUR 自动构建脚本,用来把常用的 AUR 包编译成自己的 pacman 仓库,并同步到 Cloudflare R2。

整体思路并不复杂:GitHub Actions / 容器负责构建,pikaur 负责拉取和编译 AUR 包,repo-add 负责生成仓库数据库,最后用 rclone 把产物上传到 R2。


设计目标

这套脚本主要解决几个问题:

  • 不想在本机反复编译大型 AUR 包
  • 多台 Arch 设备可以共用同一个二进制仓库
  • 构建产物需要带签名,方便 pacman 直接校验
  • 仓库文件要能低成本公开访问
  • 构建脚本和密钥配置要尽量自动化

最终效果是:只要脚本跑完,R2 上会生成完整的 pacman 仓库目录,客户端添加源之后就可以像官方源一样安装。


脚本结构

脚本大致分成几块:

1
2
3
4
5
6
script/
├── main.zsh # 初始化环境、构建仓库、上传产物
├── update_all.zsh # 批量更新需要构建的包
├── upload_script.zsh # 加密并上传脚本包
├── script.conf # 仓库名、GPG、R2 等配置
└── packages/ # 每个包的 PKGBUILD 或独立构建逻辑

核心入口是 main.zsh,它负责完成完整流水线:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
初始化 pacman / makepkg

创建专用构建用户

导入 GPG 私钥并配置签名

安装 pikaur 等构建工具

编译 AUR 包

清理旧包和 debug 包

重新生成 repo 数据库

同步到 Cloudflare R2

构建环境初始化

脚本会先启用 multilib,再把自定义的 MAKEPKG_CONF 写入 /etc/makepkg.conf

这里主要配置:

  • CFLAGS / CXXFLAGS:按机器架构优化
  • MAKEFLAGS:自动使用多线程编译
  • BUILDENV:开启包签名,关闭不需要的构建特性
  • PKGEXT:统一使用 pkg.tar.zst
  • COMPRESSZST:提高压缩效率

然后创建一个独立的 aur-build 用户,所有 AUR 构建都在这个用户下执行,避免直接用 root 跑 makepkg


包构建逻辑

普通 AUR 包可以直接放在 packages/包名/PKGBUILD 下,由 pikaur 处理依赖和构建。

对于需要特殊处理的包,则可以单独写 build.zsh。例如某些官方包需要改 PKGBUILD、禁用 strip 或调整 makepkg 配置,就可以在独立脚本里完成。

这种设计的好处是:

  • 普通包保持简单
  • 特殊包可以单独定制
  • 构建失败不会影响脚本结构
  • 后续添加新包只需要新增目录

仓库数据库生成

构建完成后,脚本不会简单地在旧数据库上继续追加,而是先清理再重建:

1
2
3
4
5
6
7
删除 debug 包

每个包只保留最新版本

删除旧的 db / files 数据库

扫描当前 pkg 目录重新 repo-add

这样可以避免几个常见问题:

  • 旧版本包长期堆积
  • 数据库里残留不存在的包
  • debug 包被意外加入仓库
  • 多次构建后仓库状态不一致

对个人仓库来说,这种“从当前产物重建数据库”的方式更可控。


上传到 Cloudflare R2

上传部分使用 rclone 的 S3 后端对接 Cloudflare R2。

配置不写入 rclone 配置文件,而是通过环境变量传入:

1
2
3
4
5
RCLONE_CONFIG_R2_TYPE=s3
RCLONE_CONFIG_R2_PROVIDER=Cloudflare
RCLONE_CONFIG_R2_ENDPOINT=...
RCLONE_CONFIG_R2_ACCESS_KEY_ID=...
RCLONE_CONFIG_R2_SECRET_ACCESS_KEY=...

这样有两个优点:

  • CI 环境里更容易注入密钥
  • 不会在命令参数里直接暴露 access key

脚本还会把 R2 endpoint 处理成 account-level endpoint,再把 bucket 名称放进路径里。这是为了避免 bucket-specific endpoint 在 list / delete / sync 场景下出现兼容问题。


相比原始方案的改进

这版脚本主要做了这些调整。

1️⃣ 上传方式改为 rclone + R2

原始方案更偏向固定对象存储上传流程,我这里统一改成 rclone sync

优点是:

  • 本地目录和远端仓库保持一致
  • 删除旧文件更自然
  • R2 / S3 兼容存储都容易迁移
  • CI 日志更容易看出同步了哪些文件

2️⃣ R2 配置集中到 script.conf

所有 R2 相关配置都放在同一个配置文件中,包括:

  • bucket 名称
  • endpoint
  • 仓库上传前缀
  • 脚本备份路径
  • access key
  • secret key

这样脚本本身只负责流程,具体环境差异都交给配置文件处理。


3️⃣ 兼容无密码 GPG 私钥

原始脚本会预设 GPG passphrase,适合带密码的私钥。

我的场景里使用的是无密码私钥,所以去掉了 gpg-preset-passphrase 相关逻辑,只保留:

1
2
3
4
5
pacman-key 导入并信任

gpg 导入到构建用户

导入后立即 shred 删除明文私钥

流程更短,也更符合当前使用方式。


4️⃣ 仓库数据库改为完全重建

直接在旧数据库上追加包,时间久了容易留下脏状态。

现在每次上传前都会:

  • 清理 debug 包
  • 使用 paccache -k1 保留最新版
  • 删除旧数据库文件
  • 对当前包目录重新执行 repo-add

这样 R2 上的仓库更像一次干净发布,而不是不断叠加的历史目录。


5️⃣ 构建脚本支持加密备份

upload_script.zsh 会用 7z 把脚本目录打包,并开启文件名加密:

1
7z a /tmp/script.7z -mhe=on -p"$PASSWORD" ./

然后把加密包上传到 R2 的指定路径。

这样即使 CI 环境临时丢失,也可以从对象存储里恢复脚本配置。当然,真正敏感的 token 和私钥仍然建议放在 CI secret 里,不要长期明文落盘。


客户端使用方式

仓库发布后,在客户端导入 GPG key,然后添加 pacman 源:

1
2
[custom]
Server = https://example.com/repo/x86_64

之后就可以直接安装:

1
2
sudo pacman -Syu
sudo pacman -S package-name

如果是私有仓库,也可以把 R2 前面接 Cloudflare Access 或者只在内网环境使用。


总结

这套脚本的重点不是“能不能构建 AUR”,而是把 AUR 构建变成一个稳定的发布流程:

  • 构建环境可重复
  • 包签名自动完成
  • 仓库数据库保持干净
  • 旧包自动清理
  • R2 上传可同步、可恢复
  • 配置和流程分离

对于只有几台 Arch 设备的个人用户来说,这种方式已经足够轻量;对于经常折腾 AUR 包、又不想在本机反复编译的人来说,也能省下不少时间。

可以白嫖的 API

整理目前可用于开发测试的免费/可白嫖 AI 推理 API 方案。


1️⃣ Qwen 免费 API + ModelScope + 轮询方案

🔹 qwen-free-api

https://github.com/LLM-Red-Team/qwen-free-api

  • 可直接调用 Qwen 相关接口
  • 适合做中转 API
  • 可多账号部署

🔹 ModelScope 官方推理 API

https://www.modelscope.cn/docs/model-service/API-Inference/intro

  • 需要绑定阿里云账号
  • 有免费额度
  • 适合正式项目调试使用

🔹 推荐轮询工具

https://github.com/tbphp/gpt-load

  • 多 Key 轮询
  • 多平台混合
  • 提高稳定性
  • 阿里云百炼也可以接入 /gpt-load 轮询

2️⃣ GitHub Models 推理 API

https://github.com/marketplace?type=models

GitHub 官方提供模型推理能力:

  • 支持 GPT-4.1 等模型
  • 通过 GitHub 账号调用
  • 适合开发测试
  • 额度有限制

优点:

  • 官方渠道
  • OpenAI 兼容接口
  • 集成方便

3️⃣ OpenRouter 免费模型路由

https://openrouter.ai/openrouter/free/providers

特点:

  • 自动路由到随机免费模型
  • OpenAI 兼容格式
  • 不需要自己维护多个模型
  • 支持 Qwen / Llama / Mistral 等

适合作为:

  • 兜底接口
  • 备用模型池
  • 开发测试

4️⃣ Qwen / iFlow 转 API + 聚合

🔹 Qwen2API

https://github.com/Rfym21/Qwen2API

  • 把 qwen.ai 转换成 API
  • 支持多账户
  • 可做 Key 池

🔹 iflow2api

https://github.com/cacaview/iflow2api

  • 把 iflowcli 转换成 API
  • 支持自动调用

🔹 推荐聚合方案

https://github.com/justlovemaki/AIClient-2-API

  • 支持多模型统一聚合
  • 可统一成 OpenAI 接口格式
  • 配置稍微复杂
  • 适合做综合 API 网关

5️⃣ Gemini 2.5 Pro 免费 API

https://github.com/su-kaka/gcli2api

  • 免费使用 Gemini-2.5-Pro
  • 通过 gcli 转 API
  • 适合做高质量输出

6️⃣ NVIDIA 免费推理 API

https://build.nvidia.com/models

  • 英伟达官方模型推理平台
  • 可使用 GLM5 等模型
  • 提供免费调用额度
  • 适合测试和研究使用

7️⃣ MiniMax 免费 OAuth 调用

参考项目:

https://github.com/openclaw/openclaw/tree/main/extensions/minimax-portal-auth

支持 MiniMax 免费 OAuth 调用。

可以使用自写脚本 minimax-oauth.js 获取 access_key
📥 下载 minimax-oauth.js

API 示例:

1
2
3
4
5
6
{
"model": "MiniMax-M2.5",
"apiKey": "your accesskey",
"provider": "openai",
"apiBase": "https://api.minimax.io/v1"
}

特点:

  • 不需要固定 API Key
  • 使用 OAuth 获取 access_key
  • 可做自动刷新

🔄 推荐组合策略

高可用白嫖方案示例:

1
2
3
4
5
6
7
8
9
OpenRouter Free

Qwen2API / qwen-free-api

Gemini gcli2api

MiniMax OAuth

NVIDIA Build API

配合 gpt-load 做轮询,实现:

  • 多模型负载均衡
  • 自动故障切换
  • 提高可用性

📌 总结

类型 推荐指数 难度 适用场景
OpenRouter ⭐⭐⭐⭐ 简单 快速接入
qwen-free-api ⭐⭐⭐⭐ 中等 稳定自建
GitHub Models ⭐⭐⭐ 简单 开发测试
Gemini gcli2api ⭐⭐⭐⭐ 中等 高质量输出
MiniMax OAuth ⭐⭐⭐⭐ 中等 自动刷新 Key
NVIDIA Build ⭐⭐⭐ 简单 研究测试

适合做:

  • 聊天机器人
  • 自动化脚本
  • 插件开发
  • 聚合 API 网关
  • 低成本生产测试环境

修复 ARM 飞牛设备相册无法加载

问题现象

在 ARM 架构的飞牛设备上,相册服务无法正常加载,查看日志发现 imagesrv 启动失败。

错误日志位置:

1
/usr/local/apps/@appdata/trim.photos/log/error.log

错误日志内容如下:


原因分析

使用 ldd 检查 imagesrv 相关依赖时,发现缺少 FFmpeg 相关动态库:

系统自带的 FFmpeg 版本不满足 imagesrv 的依赖需求,需要手动安装较新的 ARM64 版本,并正确配置 LD_LIBRARY_PATH


解决方案

1️⃣ 下载 FFmpeg(ARM64)

从官方构建仓库下载 ARM64 版本:

1
https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2025-08-31-13-00/ffmpeg-n6.1.3-linuxarm64-lgpl-shared-6.1.tar.xz

2️⃣ 解压并安装

解压到 /opt/ffmpeg6/

1
2
sudo mkdir -p /opt/ffmpeg6
sudo tar -xvf ffmpeg-n6.1.3-linuxarm64-lgpl-shared-6.1.tar.xz -C /opt/ffmpeg6 --strip-components=1

确保目录结构中包含:

1
2
3
4
/opt/ffmpeg6/
├── bin
├── lib
└── include

3️⃣ 修改 imagesrv systemd 服务

编辑服务文件:

1
sudo vi /etc/systemd/system/imagesrv.service

修改为如下内容(关键是 LD_LIBRARY_PATH):

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Imagesrv Service
After=trim_main.service

[Service]
Type=simple
ExecStart=/usr/trim/bin/imagesrv -o /usr/trim/logs/imagesrv.log -l info -u 0 -k 0 -C 1
Environment=LD_LIBRARY_PATH=/usr/trim/lib/imagesrv:/usr/trim/lib/mediasrv:/usr/trim/lib:/opt/ffmpeg6/lib
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

4️⃣ 重新加载并重启服务

1
2
sudo systemctl daemon-reload
sudo systemctl restart imagesrv

验证结果

  • imagesrv 服务正常启动
  • 相册页面可正常加载
  • 错误日志不再出现 FFmpeg 相关缺失库提示