马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
以下是针对 yum list available -c xxx.repo(对应 DNF 的命令行操纵)的详细流程解读,包括参数解析、配置初始化、元数据加载、数据库查询,以及读取不到特定包的场景分析。
1. 命令行参数解析与入口函数
代码入口: dnf.cli.main.main() -> user_main(sys.argv[1:])
- 参数处置惩罚流程:
- 参数分割:
- sys.argv[1:] 接收命令行参数,比方 ["list", "available", "-c", "xxx.repo"]。
- -c 参数指定自界说配置文件路径(覆盖默认的 /etc/dnf/dnf.conf)。
- xxx.repo 是用户自界说仓库文件(需明白路径,如 /path/to/xxx.repo)。
- CLI 解析逻辑:
- DNF 利用 argparse 解析参数,关键模块在 dnf.cli.cli.Cli 中。
- list 是子命令,对应 dnf.cli.commands.list.ListCommand 类。
- available 是 list 的子参数,表现列出未安装但仓库中存在的包。
- 关键代码片段:
- # dnf/cli/cli.py
- def parse_commands(self):
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers(dest='command')
- list_parser = subparsers.add_parser('list')
- list_parser.add_argument('available', action='store_true')
- list_parser.add_argument('-c', '--config', dest='config_file')
- return parser.parse_args()
复制代码
2. 配置初始化与仓库加载
代码模块: dnf.base.Base, dnf.conf.Conf
- 配置加载次序:
- 默认配置:
- 读取 /etc/dnf/dnf.conf,初始化全局配置对象 Conf。
- 自界说配置:
- -c xxx.repo 参数触发加载用户指定的仓库文件(可能覆盖默认仓库)。
- 仓库文件解析逻辑在 dnf.repo.RepoDict 中,关键方法为 _parse_repo_file()。
- 仓库初始化:
- 自界说仓库文件路径处置惩罚:
- # dnf/cli/cli.py
- if opts.config_file:
- conf.reposdir = [os.path.abspath(opts.config_file)]
复制代码 - 所有仓库(包括自界说仓库)生成 Repo 对象,存储在 Base.repos 中。
3. 元数据下载与 Sack 构建
代码模块: dnf.repo.Repo, dnf.sack.Sack
- 元数据加载流程:
- 元数据下载:
- 对每个启用的仓库(包括 xxx.repo 中的仓库),调用 Repo.load() 方法。
- 下载 repomd.xml 并验证署名(若配置了 gpgcheck=1)。
- 下载 primary.xml、filelists.xml 等元数据文件到缓存目录(如 /var/cache/dnf/)。
- Sack 构建:
- Base.fill_sack() 方法将所有仓库的元数据解析为 Package 对象。
- 关键代码:
- # dnf/base.py
- def fill_sack(self):
- for repo in self.repos.iter_enabled():
- repo.load() # 触发元数据下载
- self.sack = dnf.sack.Sack()
- self.sack.add_cmdline_packages() # 添加本地 RPM(此处无)
- self.sack.load_repos(self.repos) # 加载仓库元数据到 Sack
复制代码
4. 查询可用包 (list available)
代码模块: dnf.query.Query
- 查询逻辑:
- 初始化查询对象:
- # dnf/commands/list.py
- query = self.base.sack.query()
- available = query.available() # 过滤未安装的包
复制代码 - 过滤与输出:
- 根据 name、version 等条件过滤包。
- 输出效果到终端,格式化为表格。
- 关键数据布局:
- Sack 中的 packages 列表存储所有 Package 对象。
- Query 对象通过 filter() 方法实现高效检索(如 name="bash")。
5. 读取不到特定包的可能场景
以下场景可能导致无法读取仓库中的特定包信息:
场景 1: 仓库配置错误
- 缘故原由:
- xxx.repo 文件中的 baseurl 或 metalink 配置错误(如 URL 不可达)。
- 仓库未启用(enabled=0)。
- 征象:
- 实验 dnf repolist 时目的仓库未列出。
- 日志中提示 Repository 'xxx' is missing valid metadata。
场景 2: 元数据未更新
- 缘故原由:
- 本地缓存逾期(metadata_expire 超时)且未主动实验 dnf clean all 或 dnf makecache。
- 仓库元数据破坏(如 repodata 文件不完备)。
- 征象:
- 包存在于仓库服务器但本地查询不到。
- 日志提示 Cannot retrieve metalink for repository。
场景 3: 包被清除规则过滤
- 缘故原由:
- 全局配置或仓库配置中设置了 exclude=package_name。
- 启用了 --exclude 命令行参数。
- 征象:
- dnf list available 不表现目的包,但 dnf repoquery --repo=xxx package_name 可查到。
场景 4: 架构或版本不匹配
- 缘故原由:
- 包的 arch 不在系统支持的架构列表中(如 i686 包在 x86_64 系统上默认隐藏)。
- 包的 epoch:version-release 不符合仓库元数据中的界说。
- 征象:
- dnf list available 表现部门包,但特定包缺失。
场景 5: 仓库元数据未包含该包
- 缘故原由:
- 仓库服务器未正确生成元数据(如 createrepo_c 实验失败)。
- 包被手动上传到仓库目录但未添加到元数据。
- 征象:
- 通过 HTTP 直接访问仓库 URL 可看到 RPM 文件,但元数据中无记录。
完备流程示例(代码视角)
- 参数解析:
- # main.user_main(["list", "available", "-c", "xxx.repo"])
- args = Cli().parse_commands() # 解析为 {command: 'list', available: True, config_file: 'xxx.repo'}
复制代码 - 配置初始化:
- base = dnf.Base()
- base.conf.config_file_path = args.config_file # 加载 xxx.repo
- base.repos.repopulate() # 重新生成仓库列表
复制代码 - 元数据加载:
- base.repos.all().enable() # 启用所有仓库(包括自定义仓库)
- base.fill_sack() # 构建 Sack
复制代码 - 实验查询:
- query = base.sack.query().available()
- for pkg in query:
- print(pkg.name, pkg.version)
复制代码 调试与排查方法
- 检察仓库状态:
- dnf repolist -v --config=xxx.repo
复制代码 - 检查元数据缓存:
- ls /var/cache/dnf/xxx*/ # 确认 primary.xml 存在
复制代码 - 手动下载元数据:
- curl [baseurl]/repodata/repomd.xml # 验证仓库可达性
复制代码 通过以上分析,可系统化定位包信息缺失的根本缘故原由。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |