docs: add remote backup design spec and implementation plan

This commit is contained in:
RainySY
2026-05-09 14:36:22 +08:00
parent 0e524b407d
commit 5201bdac28
2 changed files with 382 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
# Remote Backup (WebDAV & SMB) Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add WebDAV upload and SMB mount backup support to the backup script using built-in busybox tools.
**Architecture:** Four config variables in `backup_settings.conf` control remote backup. Five new functions in `tools/tools.sh` handle SMB mount/unmount and WebDAV upload. A single hook in `backup_path()` triggers remote setup. The existing EXIT trap is extended to handle remote cleanup.
**Tech Stack:** Shell script (Android mksh compatible), busybox (wget, mount, umount)
---
## File Structure
| File | Action | Responsibility |
|------|--------|---------------|
| `backup_settings.conf` | Append | Remote backup configuration |
| `tools/tools.sh` | Modify | Remote backup functions + hook + trap extension |
---
### Task 1: Add remote config to backup_settings.conf
**Files:**
- Modify: `backup_settings.conf`
- [ ] **Step 1: Append remote backup configuration**
Append after line 123 (`rgb_c=177`), before the trailing newline at line 124:
```conf
#遠程備份類型 (留空不啟用)
#webdav 或 smb
remote_type=
#遠程地址
#WebDAV例: http://192.168.1.100:8080/dav/
#SMB例: //192.168.1.100/backup
remote_url=
#遠程認證用戶名
remote_user=
#遠程認證密碼
remote_pass=
```
Edit command: Use the Edit tool to append these lines after `rgb_c=177`.
- [ ] **Step 2: Verify config file**
Run: Read `backup_settings.conf` lines 120-140 to confirm the config lines are present.
- [ ] **Step 3: Commit**
```bash
git add backup_settings.conf
git commit -m "feat: add remote backup config (remote_type, remote_url, remote_user, remote_pass)"
```
---
### Task 2: Add remote backup functions to tools.sh
**Files:**
- Modify: `tools/tools.sh` (insert after line 465, before `Show_boottime` at line 466)
- [ ] **Step 1: Insert remote functions**
Insert after line 465 (`kill_Serve` call) and before line 466 (`Show_boottime()`):
```sh
# -------- 遠程備份功能 --------
mount_smb() {
local mnt="$TMPDIR/smb_mount"
mkdir -p "$mnt"
if busybox mount -t cifs "$remote_url" "$mnt" -o "username=$remote_user,password=$remote_pass,iocharset=utf8,vers=2.0" 2>/dev/null; then
SMB_MOUNT="$mnt"
[[ $(mount | grep "$mnt") != "" ]] || { echoRgb "SMB掛載失敗: $remote_url" "0"; return 1; }
echoRgb "SMB已掛載: $remote_url -> $mnt" "1"
return 0
fi
echoRgb "SMB掛載失敗回退本地備份" "0"
return 1
}
umount_smb() {
[[ -n $SMB_MOUNT ]] && {
busybox umount -l "$SMB_MOUNT" 2>/dev/null
rm -rf "$SMB_MOUNT"
unset SMB_MOUNT
echoRgb "SMB已卸載" "2"
}
}
upload_webdav() {
local base_url="${remote_url%/}"
local auth=$(echo -n "$remote_user:$remote_pass" | busybox base64)
local failed=0
local list_file="$TMPDIR/.wdav_list"
find "$Backup" -type f > "$list_file"
while read -r f; do
[[ -z $f ]] && continue
local rel="${f#$Backup/}"
echoRgb "上傳: $rel" "2"
if busybox wget -q --method PUT --body-file="$f" --header "Authorization: Basic $auth" "$base_url/$rel" 2>/dev/null; then
rm -f "$f"
else
failed=1
break
fi
done < "$list_file"
rm -f "$list_file"
if [[ $failed -eq 0 ]]; then
echoRgb "WebDAV上傳完成" "1"
else
echoRgb "WebDAV上傳失敗本地檔案已保留" "0"
return 1
fi
}
remote_setup() {
[[ -z $remote_type ]] && return
case $remote_type in
smb)
mount_smb || return
Backup="$SMB_MOUNT/Backup_${Compression_method}_$user"
mkdir -p "$Backup"
Backup_path="${Backup%/*}"
Output_path=""
echoRgb "遠程備份目錄: $Backup" "3"
;;
webdav)
echoRgb "WebDAV模式: 備份完成後將自動上傳" "3"
;;
esac
}
remote_cleanup() {
case $remote_type in
smb) umount_smb ;;
webdav) upload_webdav ;;
esac
}
```
- [ ] **Step 2: Verify insertion**
Run: Read `tools/tools.sh` lines 464-550 to confirm functions are inserted correctly and `Show_boottime()` follows.
- [ ] **Step 3: Commit**
```bash
git add tools/tools.sh
git commit -m "feat: add remote backup functions (mount_smb, umount_smb, upload_webdav, remote_setup, remote_cleanup)"
```
---
### Task 3: Wire hook and trap
**Files:**
- Modify: `tools/tools.sh` (line 462 and line 991-993)
- [ ] **Step 1: Modify EXIT trap in kill_Serve**
Change line 462 from:
```sh
trap "rm -rf '$LOCK_DIR'" EXIT
```
to:
```sh
trap "rm -rf '$LOCK_DIR'; remote_cleanup" EXIT
```
- [ ] **Step 2: Add remote_setup call at end of backup_path()**
Change line 991-993 from:
```sh
echoRgb "$hx備份資料夾所使用分區統計如下↓\n -$(df -h "${Backup%/*}" | sed -n 's|% /.*|%|p' | awk '{print $(NF-3),$(NF-2),$(NF-1),$(NF)}' | awk 'END{print "總共:"$1"已用:"$2"剩餘:"$3"使用率:"$4}')檔案系統:$(df -T "$Backup_path" | sed -n 's|% /.*|%|p' | awk '{print $(NF-4)}')\n -備份目錄輸出位置↓\n -$Backup"
echoRgb "$outshow" "2"
}
```
to:
```sh
echoRgb "$hx備份資料夾所使用分區統計如下↓\n -$(df -h "${Backup%/*}" | sed -n 's|% /.*|%|p' | awk '{print $(NF-3),$(NF-2),$(NF-1),$(NF)}' | awk 'END{print "總共:"$1"已用:"$2"剩餘:"$3"使用率:"$4}')檔案系統:$(df -T "$Backup_path" | sed -n 's|% /.*|%|p' | awk '{print $(NF-4)}')\n -備份目錄輸出位置↓\n -$Backup"
echoRgb "$outshow" "2"
remote_setup
}
```
- [ ] **Step 3: Verify EXIT trap**
Run: Read `tools/tools.sh` line 462 to confirm the trap includes `remote_cleanup`.
- [ ] **Step 4: Verify hook**
Run: Read `tools/tools.sh` lines 989-994 to confirm `remote_setup` is inside `backup_path()` before the closing `}`.
- [ ] **Step 5: Commit**
```bash
git add tools/tools.sh
git commit -m "feat: wire remote backup hook and EXIT trap"
```
---
### Task 4: Verify changes
**Files:**
- Check: `tools/tools.sh`, `backup_settings.conf`
- [ ] **Step 1: Verify git diff**
```bash
git diff master
```
Expected: ~80 lines added across 2 files:
- `backup_settings.conf`: +9 lines (remote config)
- `tools/tools.sh`: +~70 lines (functions, trap modification, hook), 1 line modified (trap), 1 line added (hook call)
- [ ] **Step 2: Verify no syntax errors in shell script**
```bash
bash -n tools/tools.sh
```
Ignore "not found" warnings for Android-specific tools — we're only checking syntax.
- [ ] **Step 3: Verify function names don't collide**
```bash
Select-String -Pattern "^(mount_smb|umount_smb|upload_webdav|remote_setup|remote_cleanup)\b" -Path tools/tools.sh
```
Expected: Each function name appears once (definition only, not duplicated).
- [ ] **Step 4: Commit any fixes if needed**
```bash
git add -A && git commit -m "fix: address verification issues"
```

View File

@@ -0,0 +1,136 @@
# Remote Backup (WebDAV & SMB) 设计文档
**日期:** 2026-05-09
**目标:** 在不涉及大范围改动的前提下,为脚本增加备份到远程 WebDAV 和 SMB 的功能。
---
## 需求
- 支持直接备份到远程 WebDAV 和 SMB 设备
- 使用脚本内置 busybox不依赖额外工具
- 配置通过 `backup_settings.conf`
- 最小化对现有代码的改动
---
## 架构
### 配置
`backup_settings.conf` 末尾追加 4 个配置项:
```conf
#远程备份类型 (留空不启用)
#webdav 或 smb
remote_type=
#远程地址
#WebDAV例: http://192.168.1.100:8080/dav/
#SMB例: //192.168.1.100/backup
remote_url=
#远程认证用户名
remote_user=
#远程认证密码
remote_pass=
```
### 新增函数tools/tools.sh
所有函数定义在 `tools/tools.sh` 中,靠近 `kill_Serve()` 之后的位置(~line 465
| 函数 | 行数 | 说明 |
|------|------|------|
| `mount_smb()` | ~10 | busybox `mount -t cifs` 挂载 SMB 到 `$TMPDIR/smb_mount` |
| `umount_smb()` | ~5 | 安全卸载 SMB 挂载点 |
| `upload_webdav()` | ~20 | 遍历备份目录,用 busybox `wget --method PUT` 逐个上传 |
| `remote_setup()` | ~25 | 入口函数SMB 挂载后设置 Output_pathWebDAV 注册 trap |
| `remote_cleanup()` | ~15 | SMB 卸载 / WebDAV 上传+清理本地文件 |
### Hook 点
`backup_path()` 调用之后line 991 附近)插入一行:
```sh
remote_setup
```
### 流程
```
backup_path() # 确定本地备份路径 $Backup
remote_setup() # 如启用远程,挂载 SMB 或准备 WebDAV uploader
[SMB] [WebDAV]
mount_smb() 正常本地备份
$Backup → mount ↓
正常备份 upload_webdav() (at EXIT)
↓ rm -rf 本地副本
umount_smb()
```
### SMB 实现细节
```sh
mount_smb() {
local mnt="$TMPDIR/smb_mount"
mkdir -p "$mnt"
busybox mount -t cifs "$remote_url" "$mnt" -o "username=$remote_user,password=$remote_pass,iocharset=utf8"
# 若 busybox mount 不支持 cifs尝试系统 mount
# 失败则返回非0remote_setup 回退到本地备份
}
```
挂载成功后,`remote_setup()``$Backup` 覆盖为 `$mnt/Backup_${Compression_method}_$user`,后续备份流程无需修改。
### WebDAV 实现细节
```sh
upload_webdav() {
local base_url="${remote_url%/}"
# 创建远程目录 (MKCOL)
busybox wget -q --method MKCOL --header "Authorization: ..." "$base_url/..." 2>/dev/null
# 遍历上传
find "$Backup" -type f | while read f; do
busybox wget -q --method PUT --body-file="$f" --header "Authorization: ..." "$base_url/..."
# 上传成功才删除本地文件
done
}
```
备份先写到本地正常流程EXIT 时 `remote_cleanup()` 触发上传,成功后删除本地副本。
### 错误处理
- SMB 挂载失败回退到本地备份echo 警告,继续执行)
- WebDAV 上传失败:保留本地文件不删除(保留数据,用户手动排查)
- SMB 连接断开trap EXIT 确保 `umount_smb()` 被调用
- 网络异常wget 自带超时,不会永久阻塞
### 恢复支持(后续迭代)
本次仅实现备份到远程。恢复从远程可在后续 PR 中补充,方向是对称实现:
- SMB挂载后从挂载点恢复
- WebDAVwget 下载到临时目录后恢复
---
## 改动范围
| 文件 | 改动 |
|------|------|
| `backup_settings.conf` | +9 行配置 |
| `tools/tools.sh` | +75 行5 个函数 + 1 个 hook 调用) |
---
## 测试要点
1. SMB 挂载成功 → 备份文件出现在远程共享目录
2. SMB 挂载失败 → 回退到本地备份,有警告提示
3. WebDAV 上传成功 → 远程有备份文件,本地副本已清理
4. WebDAV 上传失败 → 本地文件保留,有错误提示
5. EXIT 时 SMB 挂载点被正确卸载(无残留)