脚本批量下载YUM包的优化技巧
Python下载163yum源文件
处理过离线软件仓库的运维工程师都清楚,批量下载成千上万个YUM包是个怎样的体力活。看着脚本在终端里慢吞吞地跑,一个包接一个包,有时还会因为网络波动卡在半路,那种无力感比手动编译还磨人。脚本本身只是实现了“能下载”,但让它“聪明地下载”、“高效地下载”,才是区分普通脚本和可靠工具的关键。
从顺序下载到并发控制
很多初始脚本就像那个经典的Python例子,使用一个for循环顺序请求。这在包数量少时没问题,但面对CentOS仓库动辄数万个文件,这种线性下载耗时将以小时甚至天为单位计算。优化的第一刀,必须砍在并发上。
引入并发机制,例如使用Python的concurrent.futures模块或aiohttp库,可以同时发起多个下载请求。但这里有个陷阱:无限制的并发会瞬间打爆网络,甚至触发目标镜像站的连接数限制或反爬机制,导致IP被临时封禁。一个实用的技巧是使用信号量(Semaphore)或连接池,将并发数控制在一个合理的范围内,比如10到20个。这样既榨干了本地带宽,又保持了良好的网络公民形象。
断点续传与完整性校验
网络从不百分之百可靠。脚本运行到一半因为断网或人为中断而失败,难道要重头再来?优化后的脚本必须支持断点续传。利用wget的-c参数或requests库的流式下载配合文件指针,可以检查本地已存在文件的大小,然后只下载剩余部分。
更严谨的做法是,在下载完成后立即进行完整性校验。YUM仓库的repodata目录下提供了每个RPM包的校验和(通常是SHA256)。脚本应当在下载每个包后,计算其哈希值并与官方校验和对比。不匹配的包自动重新下载,这能从根本上避免因数据损坏导致的后续部署失败。
智能过滤与依赖预判
你真的需要下载整个Packages目录吗?很多时候,我们搭建本地源是为了部署特定的服务栈,比如一个LAMP环境。一股脑全盘下载,会浪费大量磁盘空间和带宽。
高级的优化技巧在于让脚本“有选择地”下载。你可以通过解析repodata/primary.xml.gz文件,这是一个包含所有包元信息(名称、版本、依赖关系)的数据库。脚本可以根据预设的包名列表(如httpd, mysql, php),递归地解析并拉取所有运行时依赖包,形成一个最小功能集合。这需要对RPM依赖关系有深入理解,但带来的资源节省是巨大的。
连接复用与超时策略
底层的网络参数调优常被忽视。为每个下载创建一个新的TCP连接,握手开销不容小觑。使用requests.Session()可以保持HTTP长连接,实现连接复用,显著降低延迟。同时,必须为连接、读取设置合理的超时时间(如连接超时10秒,读取超时30秒),并实现指数退避的重试机制。一个包下载失败,脚本应等待片刻后重试几次,而不是直接让整个任务崩溃。
最后,别忘了给脚本加上有意义的日志。它应该安静地运行,但又能随时告诉你当前进度、下载速度、失败详情和最终统计报告。当脚本能在一夜之间,无声无息地、完整无误地为你拖回整个定制化的仓库时,那种自动化带来的愉悦感,才是运维工作的精髓所在。

参与讨论
并发数设20真能跑满带宽?我上次设15都丢包了🤔
这断点续传搞起来其实挺麻烦的,得自己写校验逻辑
前几天刚搭离线源,没做依赖预判,下了80G结果用不到一半
智能过滤那块是不是得先装createrepo才能解析primary.xml?
脚本跑着睡一觉,醒来发现IP被镜像站ban了,血泪教训啊hhh
连接复用确实香,之前每次请求都新建session慢得要死