5个不稳定版本
新 0.20240826.0 | 2024年8月26日 |
---|---|
0.20240825.2 | 2024年8月25日 |
0.20240825.1 | 2024年8月25日 |
0.20240825.0 | 2024年8月24日 |
0.20240824.0 | 2024年8月24日 |
#452 in 网络编程
每月219次下载
145KB
3.5K SLoC
tsumugu
一个具有较低开销的HTTP(S)同步工具,用于OSS镜像。
与逐个文件执行HEAD
操作不同,tsumugu解析目录列表HTML,仅下载似乎未更新的文件。
设计目标
成功从这些域同步,其中lftp/rclone失败或遇到困难
待办事项
- 添加"--include": 即使文件被
--exclude
正则表达式排除,也要同步。 - 将支持的Debian、Ubuntu、Fedora和RHEL版本添加到
--include
正则表达式。- 类似于
--include debian/${DEBIAN_VERSIONS}
?
- 类似于
- 检查APT/YUM仓库的完整性(避免保留旧的无效元数据文件)
- (此为实验性,可能工作不正常)
用法
> cargo run -- --help
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
Running `target/debug/tsumugu --help`
A HTTP(S) syncing tool with lower overhead, for OSS mirrors
Usage: tsumugu <COMMAND>
Commands:
sync Sync files from upstream to local
list List files from upstream
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
> cargo run -- sync --help
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
Running `target/debug/tsumugu sync --help`
Usage: tsumugu sync [OPTIONS] <UPSTREAM> <LOCAL>
Arguments:
<UPSTREAM> The upstream URL
<LOCAL> The local directory
Options:
--user-agent <USER_AGENT>
Customize tsumugu's user agent [default: tsumugu]
--dry-run
Do not download files and cleanup
--threads <THREADS>
Threads at work [default: 2]
--no-delete
Do not clean up after sync
--max-delete <MAX_DELETE>
Set max delete count [default: 100]
--timezone-file <TIMEZONE_FILE>
You can set a valid URL for guessing. Set it to "no" to disable this behavior. By default it would recursivelly find the first file to HEAD for guessing
--timezone <TIMEZONE>
Manually set timezone (+- hrs). This overrides timezone_file
--retry <RETRY>
Retry count for each request [default: 3]
--head-before-get
Do an HEAD before actual GET. Otherwise when head-before-get and allow-time-from-parser are not set, when GETting tsumugu would try checking if we still need to download it
--parser <PARSER>
Choose a parser [default: nginx] [possible values: nginx, apache-f2, docker, directory-lister, lighttpd, caddy]
--exclude <EXCLUDE>
Excluded file regex. Supports multiple
--include <INCLUDE>
Included file regex (when it startswith any exclude regexes). Supports multiple
--skip-if-exists <SKIP_IF_EXISTS>
Skip file regex if they exist. Supports multiple
--compare-size-only <COMPARE_SIZE_ONLY>
File regex for those compare size only in HEAD requests. This only works with head_before_get
--allow-mtime-from-parser
Allow mtime from parser if not available from HTTP headers
--apt-packages
(Experimental) APT Packages file parser to find out missing packages
--yum-packages
(Experimental) YUM Packages file parser to find out missing packages
-h, --help
Print help
-V, --version
Print version
> cargo run -- list --help
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
Running `target/debug/tsumugu list --help`
Usage: tsumugu list [OPTIONS] <UPSTREAM>
Arguments:
<UPSTREAM> The upstream URL
Options:
--user-agent <USER_AGENT> Customize tsumugu's user agent [default: tsumugu]
--parser <PARSER> Choose a parser [default: nginx] [possible values: nginx, apache-f2, docker, directory-lister, lighttpd, caddy, fancy-index, gradle]
--exclude <EXCLUDE> Excluded file regex. Supports multiple
--include <INCLUDE> Included file regex (even if excluded). Supports multiple
--upstream-base <UPSTREAM_BASE> The upstream base ending with "/" [default: /]
-h, --help Print help
-V, --version Print version
有关解析器的简要介绍,请参阅./src/parser/README.md。
退出代码
- 0: 成功
- 1: 列表失败
- 2: 下载失败
- 3: 发生panic!()错误
- 4: 清理时出错
- 25: 限制停止删除
使用musl构建
遗憾的是,这需要openssl-sys,它不包括在交叉的预构建镜像中。尝试https://github.com/clux/muslrust。
评估
默认并发为2个线程。
http://download.proxmox.com/
Proxmox使用自托管的CDN服务器架构,遗憾的是,其服务器将并发限制为仅1个(根据我测试的情况)。使用传统的lftp/rclone,同步可能需要>10小时(即使本地文件与远程文件相同)。
注意:如果您只需要其APT仓库,请考虑使用Proxmox离线镜像或其他工具,如apt-mirror
。
> time ./tsumugu sync --threads 1 --dry-run --exclude '^temp' http://download.proxmox.com/ /srv/repo/proxmox/
...
real 1m48.746s
user 0m3.468s
sys 0m3.385s
https://download.docker.com/
我们之前使用一个特殊的脚本来同步docker-ce,但现在tsumugu也可以处理这个。此外,对于linux/centos/和linux/rhel/中的30x,tsumugu可以创建链接,就像这个脚本之前做的那样。
> time ./tsumugu sync --timezone-file https://download.docker.com/linux/centos/docker-ce-staging.repo --parser docker --dry-run https://download.docker.com/ /srv/repo/docker-ce/
...
real 8m32.674s
user 0m4.532s
sys 0m2.855s
https://dl.winehq.org/wine-builds/
lftp/rclone 无法处理复杂的HTML。
> time ./tsumugu sync --parser apache-f2 --dry-run --exclude '^mageia' --exclude '^macosx' --exclude '^debian' --exclude '^ubuntu' --exclude '^fedora' --include '^debian/dists/${DEBIAN_CURRENT}' --include '^ubuntu/dists/${UBUNTU_LTS}' --include '^fedora/${FEDORA_CURRENT}' https://dl.winehq.org/wine-builds/ /srv/repo/wine/wine-builds/
...
<TIMESTAMP> INFO ThreadId(01) tsumugu: (Estimated) Total objects: 17514, total size: 342.28 GiB
real 0m5.664s
user 0m1.475s
sys 0m0.294s
注意
Yuki集成
请参阅https://github.com/ustclug/ustcmirror-images#tsumugu。
YAML示例
envs:
UPSTREAM: http://download.proxmox.com/
# tsumugu is not in yuki supported upstream image yet, so this is a workaround to correctly display the upstream URL
$UPSTREAM: http://download.proxmox.com/
TSUMUGU_EXCLUDE: --exclude ^temp --exclude pmg/dists/.+changelog$ --exclude devel/dists/.+changelog$
TSUMUGU_TIMEZONEFILE: http://download.proxmox.com/images/aplinfo.dat
TSUMUGU_THREADS: 1
image: ustcmirror/tsumugu:latest
interval: 12 3 * * *
logRotCycle: 10
name: proxmox
storageDir: /srv/repo/proxmox/
更多示例在examples/。
正则表达式变量
排除和包含
目前tsumugu使用一个简单的算法来确定路径是否应该完全排除、部分排除或包含
- 在解析正则表达式时,将变量(如
${UBUNTU_LTS}
等)替换为(?<distro_ver>.+)
。 - 首先,预处理用户的排除和包含。对于所有排除,如果它是任何包含的前缀,则将其放入
list_only_regexes
,否则将其放入instant_stop_regexes
。 - 当工作线程处理列出请求时,它们将首先检查是否匹配任何
instant_stop_regexes
。如果不匹配,则检查路径是否匹配任何包含正则表达式。如果匹配,则路径将被完全排除。然后,将路径与"rev_inner"正则表达式进行匹配,如果匹配则完全排除(一个快速的快捷方式)。最后,如果路径匹配list_only_regexes
,则忽略此目录下的文件,但仍然列出子目录。不匹配任何正则表达式的路径将按常规包含。
在此过程中,一些不必要的路径仍然会被列出。将其视为简单性和性能之间的权衡。
此外,请注意,在生成用于比较的相对路径时使用这种逻辑
// Before working on one task:
let relative = task.relative.join("/");
// Before downloading a file:
let relative_filepath = PathBuf::from(&task_context.relative).join(&item.name);
let relative_filepath = relative_filepath.to_string_lossy();
item.name
,或task.relative
内的字符串,没有尾部斜杠,因此如果您想完全排除目录,则不应在正则表达式中放置尾部斜杠。
您可能会看到类似--exclude debian/ --include debian/dists/${DEBIAN_CURRENT}
的参数,其中在示例中使用了尾部斜杠排除。这仅仅是因为我们不需要排除debian文件夹的外部目录列表。
去重
tsumugu依赖于本地文件大小和mtime来检查是否应该下载文件。一些文件级别的去重程序(如jdupes)在用硬链接去重时将忽略文件mtime。这对于某些仓库来说可能是一个问题,因为一些文件会反复重新下载,因为它们在本地没有正确的mtime。
解决方案
- 设置
--compare-size-only
。 - 使用文件系统级别/块级别去重,如
zfs dedup
。 - 使用另一个考虑mtime的文件级别去重程序(尽管我不知道哪个会这样做)。
致谢
特别感谢NJU镜像的大量测试和错误报告。
命名
"tsumugu"这个名字,以及当前分支名"pudding",源自漫画《漂流少女与高贵之月》。
旧(2020年),未完成的golang版本命名为"traverse",位于main-old
分支下。
依赖
~31-46MB
~827K SLoC