4.7 KiB
4.7 KiB
TransferSu - 统一文件传输工具
基于 rsync / rclone / pv+tar 的统一拷贝管理工具,CLI/TUI 双模式,实时日志轮转, 专为"读卡器掉卡"等不稳定传输场景设计。
特性
- 多后端: rsync(推荐, 断点续传)/ rclone(并行)/ pv+tar(零依赖)
- CLI/TUI 双模式: 未显式
--mode cli时默认 TUI 启动 - TUI 四栏布局:
- 上栏: 总进度条(字节) + 单文件进度条(文件计数)
- 中栏: 速度曲线可视化(当前/峰值/平均速度实时文字)
- 下栏: 文件日志 + 错误日志 双面板
- 底部: 交互输入栏(空启动设定任务 / 传输控制命令)
- 进度轮询机制: 每秒主动统计目标目录大小驱动进度, 绕过后端输出缓冲(Android 上 stdbuf/LD_PRELOAD 无效,rsync 输出全缓冲不可靠)
- 掉卡自愈:
--retry -1无限自动补传 + 完成后--verify校验 - 实时日志: 写入本地目录, 滚动保留最近 N 个(默认 20), 纳秒时间戳排序
安装
pip install -i https://mirrors.aliyun.com/pypi/simple/ pytest textual
用法
# TUI 模式 (默认): 空启动后在底部输入栏设定任务
python3 transfer.py
# TUI 模式带预设任务
python3 transfer.py /src /dst --bwlimit 30000
# CLI 模式 (显式指定)
python3 transfer.py --mode cli /src/ /dst/ --backend rclone --bwlimit 8M
TUI 输入栏命令
/src /dst --bwlimit 30000 --retry -1 --verify # 启动传输任务
stop # 停止当前任务 (SIGTERM, 跳过补传)
pause # 暂停 (SIGSTOP, 轮询同步挂起)
continue # 恢复暂停 (SIGCONT)
help / clear / quit
进度显示:
- 总进度条: 已传字节/源总量(每秒轮询刷新)
- 单文件进度条: 文件计数(目标文件数/源文件总数, 每 3 秒刷新)
- 速度曲线栏: 当前/峰值/平均速度文字 + Sparkline 曲线
参数
| 参数 | 默认 | 说明 |
|---|---|---|
--backend |
rsync | rsync / rclone / tar |
--bwlimit |
30000 | 限速 (rsync: KB/s, rclone: 如 8M) |
--transfers |
4 | rclone 并行传输数 |
--resume / --no-resume |
开 | rsync 断点续传 |
--checksum |
关 | rsync 校验模式 |
--verify |
关 | 完成后校验(rsync -c dry-run, 0 差异=一致) |
--retry |
0 | 失败自动补传轮数, -1 = 无限重试 |
--policy |
overwrite | 冲突策略: overwrite / skip / ask |
--mode |
tui | cli / tui |
--keep-logs |
20 | 日志滚动保留数 |
--logdir |
~/logs | 日志目录 |
掉卡场景最佳实践
读卡器/移动硬盘在安卓上高速写入可能 USB 掉线(如 GL3224 芯片)。 完整方案:
- 守护脚本自动恢复设备(掉线后重枚举):
su -c 'setsid sh /data/local/tmp/usb_guard.sh </dev/null >/dev/null 2>&1 &' - 限速传输 + 无限补传 + 校验:
/src/ /dst/ --bwlimit 30000 --retry -1 --verify - 掉卡时: 守护恢复设备 → TransferSu 自动重跑补传(
--partial只补缺失)→ 直到成功 →rsync -c全量校验(0 差异 = 源目标完全一致)
rsync 原子写(临时文件+rename)保证掉卡不会产生半截损坏的正式文件, 残留临时文件由补传后的
--verify流程发现处理。
日志
- 目录:
--logdir指定(默认~/logs) - 文件名:
{时间戳}_{后端}_{源名}.log(时间戳开头, 排序即时间序) - 滚动: 超过
--keep-logs个自动删除最旧 - 内容: 命令/源大小/补传轮次/退出码(含帧数)/校验结果/错误行
冲突策略(覆盖/跳过)
| 参数 | 行为 |
|---|---|
--overwrite |
覆盖已存在文件(默认) |
--skip |
跳过已存在文件(--ignore-existing) |
--ask |
逐项询问(扫描冲突后交互) |
ask 交互选项(CLI 与 TUI 一致):
y = 覆盖当前项 n = 跳过当前项
a = 全部覆盖 s = 全部跳过
q = 中止传输
- CLI: 预扫描后逐项提示
- TUI: 扫描完成后在底部输入栏逐项交互
- 仅当前/后续同步: y/n 只作用当前文件; a/s 一次决定后续(已明确决策的保留)
- rsync 覆盖场景自动禁用
--append(追加模式阻止重写), 保留--partial - rclone 的
--ask用原生--interactive(y/n/s); tar 后端不支持 ask/skip
# CLI 示例
python3 transfer.py --mode cli --policy ask --retry 5 --verify /src/ /dst/
python3 transfer.py --mode cli --retry -1 --verify /src/ /dst/
# TUI 输入栏示例
/src /dst --policy ask --retry 5 --verify
/src /dst --retry -1 --verify
测试
python3 -m pytest tests/ -q
54 个单元测试: 解析器 / 日志轮转 / 参数解析 / 后端命令 / 冲突决策 / 目录轮询 / 暂停信号 / 校验命令。