wheelnext 包的构建原理、结构分析与安装流程
简介随着异构算力与多样化运行环境的普及，同一 Python 发行包在不同硬件、驱动与系统组合上的适配差异日益显著。传统“单一 wheel 适配全部环境”的分发模型通常面临两类问题：一是依赖运行时探测与兼容分支，导致部署链路复杂、行为不确定性上升；二是通过拆分多发行包实现适配，带来命名体系扩张、发布流程冗余与运维成本增加。wheelnext 引入的 Variant 机制，目标是在不破坏既有包名与版本语义的前提下，为同一版本提供可按平台能力精确匹配的 wheel 变体在该体系中，variantlib 与 uv-wheelnext 分别承担构建侧与安装侧职责。variantlib 负责对基础 wheel 注入变体元数据、生成带变体标识的产物，并输出用于分发侧索引的 variants.json；uv-wheelnext 负责在安装阶段解析变体索引、加载 provider 插件获取环境能力、执行候选变体过滤与排序，并确定最终安装目标。两者协同后，可形成“发布阶段声明差异、安装阶段自动匹配”的闭环流程本文以 vllm_ascend 为案例，围绕变体包生命周期展开分析：首先说明如何使用 variantlib 构建变体包；其次通过拆包比对定位原始包与变体包的结构差异及其来源；最后结合实际安装日志，复盘 uv-wheelnext 的识别、匹配与选择过程，建立从构建到安装的端到端技术认知1 使用 variantlib 生成变体包本章以原始包 vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64.whl 为例，详述如何通过注入变体信息 ascend :: npu_type :: a2 生成变体包 vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl，以便更好理解变体包内部结构的变化及产生变化的内容来源1.1 安装 uv-wheelnext参考文档：An experimental, variant-enabled build of uv# 执行以下命令安装 $ curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_DOWNLOAD_URL=https://wheelnext.astral.sh sh # 执行以下命令刷新 PATH 环境变量 $ source $HOME/.local/bin/env # 查看版本号，可以发现命令仍为 uv，但版本已经带有 uv-wheelnext $ uv --version uv-wheelnext 0.8.41.2 安装 variantlib 工具# 克隆 variantlib 源代码 $ git clone https://github.com/wheelnext/variantlib.git # 进入克隆的 variantlib 源代码目录 $ cd variantlib # 创建虚拟环境 $ uv venv # 安装 variantlib $ uv pip install --system . # 查看版本号，确认安装是否成功 $ variantlib --version variantlib version: 0.0.31.3 生成变体包1.3.1 准备 pyproject.toml 文件编写 pyproject.toml 文件（必须）：[variant.default-priorities] namespace = ["ascend"] [variant.providers.ascend] enable-if = "platform_system == 'Linux'" plugin-api = "huawei_ascend_variant_provider.plugin:AscendVariantPlugin" requires = ["huawei-ascend-variant-provider>=0.0.1,<1.0.0"]关于 pyproject.toml 文件，有以下几点注意：文件名称可以随意命名，不必须为 pyproject.tomlvariantlib 在注入变体信息过程中，只是读取 pyproject.toml，并不会对其修改该 pyproject.toml 文件与 vllm_ascend 项目本身的 pyproject.toml 并无关联，因此有两种用法：新建 pyproject.toml（可任意命名），只需写入以上的 variant 信息即可在 vllm_ascend 项目原有的 pyproject.toml 中追加 variant 信息1.3.2 生成变体包执行以下命令，注入变体信息，生成变体包：$ variantlib make-variant \ -f vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64.whl \ -o ./ \ --pyproject-toml pyproject.toml \ --property "ascend :: npu_type :: a2" \ --variant-label a2 \ --skip-plugin-validationvariantlib make-variant 命令相关选项及作用如下：命令选项作用-f指定基础 wheel 包-o指定输出变体包的位置--pyproject-toml指定包含 variant 信息的 pyproject.toml--property指定变体特征--variant-label指定变体包的变体后缀，如 -a2、-a3--skip-plugin-validation跳过使用 provider 校验执行以下命令，校验变体包属性：$ variantlib analyze-wheel \ -i vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl variantlib.commands.analyze_wheel - INFO - Filepath: `vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl` ... is a Wheel Variant - Label: `a2` ############################## Variant: `38edb458` ############################# ascend :: npu_type :: a2 ################################################################################执行以下命令，为指定目录下的所有变体包生成索引文件：$ variantlib generate-index-json -d ./2 原始包与变体包的结构分析根据第 1 章的操作，成功构建出变体包 vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl，以下将通过拆包对比的方法，分析注入变体信息过程中，产生了哪些变化以及变化的来源2.1 原始包与变体包名称差异原始包名称：vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64.whl变体包名称：vllm_ascend-0.13.0rc1-cp311-cp311-manylinux_2_24_x86_64-a2.whl对比这两个包的名称可以发现，变体包多了一个变体后缀 -a2。关于变体后缀，参考以下说明：来源： 有以下两种来源（参考代码：variantlib/api.py:347-364）由 variantlib make-variant 命令的 --variant-label 选项指定若没有指定，则根据变体属性计算 SHA256 取前 8 位作为 label作用： 用于判断指定的包是否为变体包（参考代码：variantlib/commands/analyze_wheel.py:54-64）若变体后缀存在，则认为该包为变体包若变体后缀不存在，则认为该包为普通包2.2 原始包与变体包结构差异使用 unzip 命令分别解压原始包与变体包，查看其结构差异原始包的结构如下：. ├── vllm_ascend │ ├── ascend_config.py │ ├── ...... │ └── xlite └── vllm_ascend-0.13.0rc1.dist-info ├── entry_points.txt ├── LICENSE ├── METADATA ├── RECORD ├── top_level.txt └── WHEEL 20 directories, 20 files变体包的结构如下：. ├── vllm_ascend │ ├── ascend_config.py │ ├── ...... │ └── xlite └── vllm_ascend-0.13.0rc1.dist-info ├── entry_points.txt ├── LICENSE ├── METADATA ├── RECORD ├── top_level.txt ├── variant.json └── WHEEL 20 directories, 21 files对比原始包与变体包结构发现，在变体包的 .dist-info 目录下多出一个 variant.json 文件。关于该文件，有以下信息（参考代码：variantlib/commands/make_variant.py:241-287）：该文件在注入变体信息，构建变体包时产生与其他文件相同，该文件的 SHA256 值同样会被记录到 .dist-info/RECORD 文件中：vllm_ascend-0.13.0rc1.dist-info/variant.json,sha256=3LE9xShDUHoYkI1LktyD3Dq4n0JJLM5U_DSM_DQajrg,624除该文件及 .dist-info/RECORD 文件之外，其他文件完全不变该文件的内容来源参考以下 2.3 节2.3 variant.json 文件内容的来源查看 variant.json 文件内容：{ "$schema": "https://variants-schema.wheelnext.dev/v0.0.3.json", "default-priorities": { "namespace": [ "ascend" ] }, "providers": { "ascend": { "enable-if": "platform_system == 'Linux'", "plugin-api": "huawei_ascend_variant_provider.plugin:AscendVariantPlugin", "requires": [ "huawei-ascend-variant-provider>=0.0.1,<1.0.0" ] } }, "variants": { "a2": { "ascend": { "npu_type": [ "a2" ] } } } }该文件的内容来源及作用如下（参考代码：variantlib/api.py:173-272）：$schema：来源：硬编码常量 VARIANTS_JSON_SCHEMA_URL作用：标明该 variant.json 文件遵循的是 wheelnext 变体规范的 v0.0.3 版本，便于工具（如 uv-wheelnext）根据版本号正确解析支持 JSON Schema 的编辑器或工具可以据此自动校验 variant.json 的结构是否合法default-priorities：来源：variantlib make-variant 命令 --pyproject-toml 选项指定的 pyproject.toml 文件。若该文件没有包含 [variant.*] 配置信息，则字段值为空作用（参考代码：variantlib/resolver/sorting.py）：控制变体候选的排序优先级，列表中靠前的 namespace 优先级更高安装时，包管理器通过 provider 插件获取当前平台支持的属性后，用此优先级对可用变体排序，选出最佳匹配providers：来源：与 default-priorities 相同作用： 定义如何加载和调用 provider 插件来获取当前平台的变体属性（参考代码：variantlib/plugins/loader.py）enable-if：环境标记表达式，安装时评估此条件决定是否加载该插件plugin-api：插件的导入路径（如 module:ClassName），用于动态加载插件实例requires：该插件的依赖包列表，安装时需要先确保这些依赖可用variants：来源：key： 与变体包的变体后缀一致，参考 2.1 原始包与变体包名称差异value： 按 namespace → feature → [values] 嵌套的属性字典，由 variantlib make-variant 命令的 --property 选项指定作用：声明该包所有已构建的变体组合及其属性值（参考代码：variantlib/resolver/filtering.py）安装时，将每个变体的属性与当前平台（通过 provider 插件查询到的）支持的属性做匹配过滤多个属性间是 AND 关系（必须全部满足），单个属性的多个 value 间是 OR 关系（满足任一即可）过滤后的变体再按 default-priorities 排序，选出最优变体安装3 uv-wheelnext 如何识别安装变体包在 a3 服务器上执行以下命令安装变体包 vllm-ascend，查看其输出日志，以分析安装流程：$ uv pip install -v --prerelease=allow \ --extra-index-url https://mirrors.huaweicloud.com/ascend/repos/pypi/variant \ vllm-ascend安装过程打印如下：# ==================== 阶段一：环境探测 ==================== DEBUG uv 0.8.4 DEBUG Searching for default Python interpreter in virtual environments DEBUG Found `cpython-3.11.14-linux-aarch64-gnu` at `/root/yzc/wheel/bin/python3` (active virtual environment) Using Python 3.11.14 environment at: wheel DEBUG Acquired lock for `wheel` DEBUG At least one requirement is not satisfied: vllm-ascend DEBUG Using request timeout of 30s DEBUG Solving with installed Python version: 3.11.14 DEBUG Solving with target Python version: >=3.11.14 DEBUG Adding direct dependency: vllm-ascend* # ==================== 阶段二：索引发现 ==================== DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/vllm-ascend/ WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: WARN Skipping file for vllm-ascend: register.html DEBUG Searching for a compatible version of vllm-ascend (*) # ==================== 阶段三：变体索引获取 ==================== DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/vllm-ascend/vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64.whl DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/vllm-ascend/vllm_ascend-0.17.0rc1-variants.json # ==================== 阶段四：Provider 插件查询 ==================== DEBUG Querying provider `ascend` for variants DEBUG Using base executable for virtual environment: /usr/local/python3.11.14/bin/python3.11 DEBUG Solving with installed Python version: 3.11.14 DEBUG Solving with target Python version: >=3.11.14 DEBUG Adding direct dependency: huawei-ascend-variant-provider>=0.0.2, <1.0.0 DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/huawei-ascend-variant-provider/ DEBUG Searching for a compatible version of huawei-ascend-variant-provider (>=0.0.2, <1.0.0) DEBUG Selecting: huawei-ascend-variant-provider==0.0.2 [compatible] (huawei_ascend_variant_provider-0.0.2-py3-none-any.whl) DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/huawei-ascend-variant-provider/huawei_ascend_variant_provider-0.0.2-py3-none-any.whl DEBUG Tried 1 versions: huawei-ascend-variant-provider 1 DEBUG marker environment resolution took 0.193s DEBUG Installing in huawei-ascend-variant-provider==0.0.2 in /root/.cache/uv/wheelnext-builds-v0/.tmpuuXXg1 DEBUG Identified uncached distribution: huawei-ascend-variant-provider==0.0.2 (huawei_ascend_variant_provider-0.0.2-py3-none-any.whl) DEBUG Downloading and building requirement for build: huawei-ascend-variant-provider==0.0.2 DEBUG No cache entry for: https://mirrors.huaweicloud.com/ascend/repos/pypi/variant/huawei-ascend-variant-provider/huawei_ascend_variant_provider-0.0.2-py3-none-any.whl DEBUG Installing build requirement: huawei-ascend-variant-provider==0.0.2 # ==================== 阶段五：变体选择与安装 ==================== DEBUG Using variant wheel vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl DEBUG Selecting: vllm-ascend==0.17.0rc1 [compatible] (vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl) DEBUG Adding transitive dependency for vllm-ascend==0.17.0rc1: cmake>=3.26 DEBUG Adding transitive dependency for vllm-ascend==0.17.0rc1: decorator* ......根据以上安装日志，uv-wheelnext 识别并安装变体包的完整流程可分为五个阶段3.1 环境探测DEBUG Searching for default Python interpreter in virtual environments DEBUG Found `cpython-3.11.14-linux-aarch64-gnu` at `/root/yzc/wheel/bin/python3` DEBUG Solving with installed Python version: 3.11.14uv-wheelnext 首先探测当前 Python 环境：确定解释器版本（3.11.14）确定平台架构（linux-aarch64）确定 ABI 标签（cp311）这些信息将作为后续 wheel 兼容性过滤的基础条件3.2 索引发现DEBUG No cache entry for: .../vllm-ascend/ DEBUG Searching for a compatible version of vllm-ascend (*)uv-wheelnext 向 --extra-index-url 指定的变体索引源发起请求，获取 vllm-ascend 的可用版本列表此阶段与标准 pip 安装一致，遍历索引页面中的所有文件链接，跳过不兼容的文件（如 HTML 页面、不匹配的平台标签等）3.3 变体索引获取DEBUG No cache entry for: .../vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64.whl DEBUG No cache entry for: .../vllm_ascend-0.17.0rc1-variants.json这是 uv-wheelnext 区别于标准 uv 的核心步骤。在找到兼容的 wheel 文件后，uv-wheelnext 会额外请求同目录下的 {name}-{version}-variants.json 文件。该文件由 variantlib generate-index-json 命令预先生成，其内容与结构如见 2.3 variant.json 文件内容的来源variants.json 是变体包的索引文件，它声明了该版本所有可用的变体标签及其属性，以及对应的 provider 插件信息。uv-wheelnext 正是通过该文件发现"此包存在变体"，从而进入变体解析流程。3.4 Provider 插件查询DEBUG Querying provider `ascend` for variants DEBUG Adding direct dependency: huawei-ascend-variant-provider>=0.0.2, <1.0.0 DEBUG Installing build requirement: huawei-ascend-variant-provider==0.0.2uv-wheelnext 从 variants.json 的 providers 字段中读取 provider 插件信息，执行以下操作：解析 requires 字段，将 huawei-ascend-variant-provider>=0.0.2,<1.0.0 作为临时依赖进行解析和安装将 provider 插件安装到隔离的临时环境 /root/.cache/uv/wheelnext-builds-v0/.tmpuuXXg1，避免污染用户环境通过 plugin-api 字段指定的入口点（huawei_ascend_variant_provider.plugin:AscendVariantPlugin）加载插件实例调用插件的 get_supported_configs() 方法，查询当前平台支持的变体属性（参考代码：variantlib/api.py:68-78）例如在昇腾 a3 设备上，provider 插件会返回 ascend :: npu_type :: a3，表示当前平台支持该变体属性3.5 变体匹配、排序与选择DEBUG Using variant wheel vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl DEBUG Selecting: vllm-ascend==0.17.0rc1 [compatible]获取到平台支持的变体属性后，uv-wheelnext 将完成最终选择，具体步骤如下：过滤（filter_variants）：遍历 variants.json 中声明的所有变体，将每个变体的属性与平台支持的属性进行匹配。多个属性间为 AND 关系（必须全部满足），单个属性的多个 value 间为 OR 关系（满足任一即可）。不兼容的变体被淘汰注入 Null Variant：始终将空属性的 null variant 加入候选列表作为兜底，确保即使没有匹配的变体，也能回退到基础包排序（sort_variants_descriptions）：根据 default-priorities 中定义的 namespace、feature、property 优先级，对通过过滤的变体进行排序，优先级高的排在前面选择：取排序后的第一个变体作为最优匹配。本例中，变体 a3（属性 ascend :: npu_type :: a3）与当前平台完全匹配，因此 uv-wheelnext 最终选择安装 vllm_ascend-0.17.0rc1-cp311-cp311-manylinux_2_24_aarch64-a3.whl
1 问题现状在讨论问题之前，先假设这样的场景：某服务器管理员忘记了 root 用户的密码，不能登录服务器，此时需要进行怎样的操作来重置 root 用户的密码呢？一般的操作流程如下：重启服务器进入 grub2 界面（选择内核的界面）按 “e” 进入 grub2 配置界面，找到 linux 开头的行，将该行中的 ro 修改为 rw，并在该行的末尾加上 init=/bin/sh使用组合键 “ctrl+x” 进入单用户模式，获得 shell 操作界面，执行 passwd root 命令为 root 用户设置密码若 SELinux 为 Enforcing 状态，则还需要执行 touch /.autorelabel 命令以使系统重新打标签退出单用户，重启服务器，使用新的 root 用户密码登录系统从以上处理流程可以看到，即使在不知道服务器 root 用户密码的情况下，只要能接触到物理服务器，也能通过一系列操作进入系统。因此，出于安全考虑，对 grub2 加密是有必要的。以下内容摘自官方文档：GRUB (GRand UnifiedBootloader) 是操作系统启动管理器，用来引导不同系统（如Windows、Linux）。GRUB2 是 GRUB 的升级版。系统启动时，可以通过 GRUB2 界面修改启动参数。为了确保系统的启动参数不被任意修改，需要对 GRUB2 界面进行加密，仅在输入正确的 GRUB2 口令时才能修改openEuler 操作系统默认为 grub2 进行了加密并设置了密码，登录 grub2 的用户名为 root，登陆密码为 openEuler#12。官方文档也进行了说明，详见：帐号清单虽然对 grub2 设置密码比较安全，但是机房重地，并非人人都能接触到物理服务器。因此在某些场景下为 grub2 加密反而使操作变得繁琐，在实际生产中，也遇到很多想要取消 grub2 加密的需求，以下就该问题提出完整的解决方案2 如何取消 grub2 加密2.1 临时方案直接修改 /boot/efi/EFI/openEuler/grub.cfg 或 /boot/grub2/grub.cfg 文件，当然也可以修改 /etc/grub2-efi.cfg 文件（与前述文件是软链接关系），将如下代码删除：set superusers=root password_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08删除上述代码后，再次重启系统进入 grub2 就不再需要输入密码。然而作为临时方案，这种操作是不能永久生效的当执行了 grub2-mkconfig -o /path/to/grub.cfg 命令或执行了能触发该命令的操作时，都会重新生成 grub.cfg 文件，使得被删除的代码又重新写入2.2 永久方案只要删除 /etc/grub.d/00_header 文件末尾 cat <<EOF ... EOF 部分的代码，即可实现永久取消 grub2 加密在临时方案中修改 grub.cfg 文件时，注意到删除的代码位于以下两行注释中：### BEGIN /etc/grub.d/00_header ### ...... set superusers=root password_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08 ### END /etc/grub.d/00_header ###可见这两行用于加密的代码来自于 /etc/grub.d/00_header 文件，那么接下来修改这个文件。该文件末尾有以下代码，表示在生成 grub.cfg 文件时，通过 cat <<EOF ... EOF 命令将加密的代码写入 grub.cfg 文件：cat <<EOF set superusers=root password_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08 EOF因此只要删除 /etc/grub.d/00_header 文件末尾 cat <<EOF ... EOF 部分的代码，即可实现永久取消 grub2 加密2.3 彻底解决方案删除 /usr/sbin/security-tool.sh 文件第 948 行的代码删除的代码内容如下：echo -e "cat <<EOF\nset superusers="root"\npassword_pbkdf2 root grub.pbkdf2.sha512.10000.5A45748D892672FDA02DD3B6F7AE390AC6E6D532A600D4AC477D25C7D087644697D8A0894DFED9D86DC2A27F4E01D925C46417A225FC099C12DBD3D7D49A7425.2BD2F5BF4907DCC389CC5D165DB85CC3E2C94C8F9A30B01DACAA9CD552B731BA1DD3B7CC2C765704D55B8CD962D2AEF19A753CBE9B8464E2B1EB39A3BB4EAB08\nEOF\n" >> /etc/grub.d/00_header在永久解决方案中，/etc/grub.d/00_header 文件末尾 cat <<EOF ... EOF 部分的代码也不是凭空产生的，而是由 /usr/sbin/security-tool.sh 这个文件的第 948 行代码写入的，因此只要将其删除，即可从源头上取消 grub2 加密3 总结grub2 加密的流程为：先通过 /usr/sbin/security-tool.sh 文件第 948 行的代码将加密指令写入 /etc/grub.d/00_header 文件末尾再通过/etc/grub.d/00_header 文件末尾的加密指令，将加密内容写入 grub.cfg 文件系统启动时读取 grub.cfg 文件的加密内容从而对 grub2 加密在了解 grub2 加密的流程后，就可以在每个阶段进行操作，从而达到彻底取消、永久取消、临时取消 grub2 加密的目的
openEuler-20.03-LTSx86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP1x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/EPOL/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/EPOL/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP2x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP3x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0openEuler-20.03-LTS-SP4x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-20.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-20.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTSx86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP1x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP2x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP3x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0openEuler-22.03-LTS-SP4x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTSx86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTS-SP1x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP1/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTS-SP2x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP2/update/aarch64/ enabled=1 gpgcheck=0openEuler-24.03-LTS-SP3x86_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0x86_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/update/x86_64/ enabled=1 gpgcheck=0aarch64_华为云[openEuler-everything] name=openEuler-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-24.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0aarch64_openEuler[openEuler-everything] name=openEuler-everything baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/everything/aarch64/ enabled=1 gpgcheck=0 [openEuler-EPOL] name=openEuler-epol baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/EPOL/main/aarch64/ enabled=1 gpgcheck=0 [openEuler-update] name=openEuler-update baseurl=http://repo.openeuler.org/openEuler-24.03-LTS-SP3/update/aarch64/ enabled=1 gpgcheck=0
1 配置全局代理PROXY_IP=192.168.230.1 PROXY_PORT=10808 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=socks://${PROXY_IP}:${PROXY_PORT}2 修改 repo 源2.1 将官方源修改为华为源\cp -a /etc/yum.repos.d/openEuler.repo /etc/yum.repos.d/openEuler.repo.origin sed -i \ -e '/^metalink/ s/^\(.*\)$/#\1/g' \ -e 's/repo.openeuler.org/repo.huaweicloud.com\/openeuler/g' \ /etc/yum.repos.d/openEuler.repo dnf clean all && dnf makecache2.2 将华为源修改为官方源\cp -a /etc/yum.repos.d/openEuler.repo /etc/yum.repos.d/openEuler.repo.hauwei sed -i \ -e '/^meta/ s/^\(.*\)$/#\1/g' \ -e 's/repo.huaweicloud.com\/openeuler/repo.openeuler.org/g' \ /etc/yum.repos.d/openEuler.repo dnf clean all && dnf makecache2.3修改源中的系统版本curr_version=$(grep -o 'openEuler-[^/]*' openEuler.repo | sort -u) && echo ${curr_version} dest_version=openEuler-24.03-LTS-SP2 sed -i \ -e '/^meta/ s/^\(.*\)$/#\1/g' \ -e "s/${curr_version}/${dest_version}/g" \ /etc/yum.repos.d/openEuler.repo dnf clean all && dnf makecache3 环境配置3.1 配置 go 编译环境# 定义要安装的 go 版本及架构（amd64、arm64） $ GO_VERSION=1.22.11; GO_ARCH=amd64 # 下载 go 二进制包 $ wget https://golang.google.cn/dl/go"${GO_VERSION}".linux-"${GO_ARCH}".tar.gz -P /root # 解压 go 二进制包到指定目录 $ rm -rf /usr/local/go && tar -xvf go"${GO_VERSION}".linux-"${GO_ARCH}".tar.gz -C /usr/local # 配置 go 开发需要的环境变量 $ cat >> /etc/profile <<"EOF" export GOPATH=/root/go export GOBIN=${GOPATH}/bin export GOROOT=/usr/local/go export PATH=${PATH}:${GOROOT}/bin EOF # 重载环境变量 $ source /etc/profile # 查看 go 版本 $ go version3.2 配置 jdk 环境# 解压下载的 jdk $ tar -xvf jdk-11.0.27_linux-x64_bin.tar.gz -C /usr/local # 创建软链接，方便版本管理 $ ln -s /usr/local/jdk-11.0.27 /usr/local/java # 配置环境变量 $ sed -i \ -e '$a \ ' \ -e '$a export JAVA_HOME=/usr/local/java' \ -e '$a export JAVA_BIN=${JAVA_HOME}/bin' \ -e '$a export PATH=${JAVA_BIN}:${PATH}' \ /etc/profile # 刷新环境变量 $ source /etc/profile # 查看 java 版本 $ java -version java version "11.0.27" 2025-04-15 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.27+8-LTS-232) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.27+8-LTS-232, mixed mode)4 下载相关4.1 wget（1）配置全局禁用证书验证echo -e "\ncheck_certificate = off" >> /etc/wgetrc4.2 git（1）配置全局禁用证书验证git config --global http.sslVerify false（2）配置国内代理$4.3 go（1）配置国内代理export GOPROXY=https://goproxy.io,direct4.4 pip（1）配置站点可信mkdir ~/.pip cat > ~/.pip/pip.conf <<EOF [global] index-url = https://mirrors.huaweicloud.com/repository/pypi/simple trusted-host = mirrors.huaweicloud.com timeout = 120 EOF4.5 gem（1）配置全局禁用证书验证echo ":ssl_verify_mode: 0" >> ~/.gemrc（2）配置国内代理cat >> ~/.gemrc <<-EOF :sources: - https://gems.ruby-china.com/ EOF5 开启系统 debug 日志# 开启 systemd 的 debug 日志 $ sed -i '/LogLevel=.*/c LogLevel=debug' /etc/systemd/system.conf # 开启 journal 的 debug 日志 $ sed -i -e '/^\[Journal\]/a LogLevel=debug' \ -e '/^\[Journal\]/a LogTarget=journald' \ /etc/systemd/journald.conf # 开启内核 debug 日志 $ sed -i '/^GRUB_CMDLINE_LINUX=.*/ s/\"$/ rd.debug\"/' /etc/default/grub $ [ -d "/sys/firmware/efi" ] && grub2-mkconfig -o /boot/efi/EFI/$(cat /etc/os-release | grep -w ID | awk -F '"' '{print$2}')/grub.cfg || grub2-mkconfig -o /boot/grub2/grub.cfg
1 环境准备本文所有环境基于 openEuler 22.03 LTS SP4 操作系统1.1 网络环境# 配置代理 PROXY_IP=192.168.230.1 PROXY_PORT=10809 export http_proxy=http://${PROXY_IP}:${PROXY_PORT} export https_proxy=http://${PROXY_IP}:${PROXY_PORT} export ALL_PROXY=http://${PROXY_IP}:${PROXY_PORT} export all_proxy=socks://${PROXY_IP}:${PROXY_PORT}1.2 安装 cuda# 安装基础工具及内核开发包 $ yum install -y gcc-c++ make dkms kernel-source-$(uname -r) kernel-devel-$(uname -r) # 下载 cuda 包 $ wget https://repo.oepkgs.net/openEuler/rpm/openEuler-22.03-LTS-SP4/contrib/drivers/x86_64/Packages/cuda_12.4.0_550.54.14_linux.run -P /root # 安装 cuda 包 $ sh /root/cuda_12.4.0_550.54.14_linux.run ...... =========== = Summary = =========== Driver: Installed Toolkit: Installed in /usr/local/cuda-12.4/ Please make sure that - PATH includes /usr/local/cuda-12.4/bin - LD_LIBRARY_PATH includes /usr/local/cuda-12.4/lib64, or, add /usr/local/cuda-12.4/lib64 to /etc/ld.so.conf and run ldconfig as root To uninstall the CUDA Toolkit, run cuda-uninstaller in /usr/local/cuda-12.4/bin To uninstall the NVIDIA Driver, run nvidia-uninstall Logfile is /var/log/cuda-installer.log # 配置 PATH 变量 $ sed -i \ -e '$a \ ' \ -e "\$a export PATH=$PATH" \ -e '$a export PATH=$PATH:/usr/local/cuda-12.4/bin' \ /etc/profile # 刷新 /etc/profile 文件 $ source /etc/profile # 配置库文件 $ sed -i '$a /usr/local/cuda-12.4/lib64' /etc/ld.so.conf # 刷新动态链接库 $ ldconfig # 查看 Nvidia 驱动版本 $ nvidia-smi # 查看 cuda 版本 $ nvcc --version nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2024 NVIDIA Corporation Built on Tue_Feb_27_16:19:38_PST_2024 Cuda compilation tools, release 12.4, V12.4.99 Build cuda_12.4.r12.4/compiler.33961263_01.3 安装 docker1.3.1 安装 docker# 定义要安装的 docker 版本及架构（x86_64、aarch64） $ DOCKER_VERSION=26.0.0; DOCKER_ARCH=x86_64 # 从官方仓库下载二进制 docker 压缩包 $ wget https://download.docker.com/linux/static/stable/"${DOCKER_ARCH}"/docker-"${DOCKER_VERSION}".tgz -P /root # 解压下载的压缩包 $ tar -xvf /root/docker-"${DOCKER_VERSION}".tgz -C /root # 复制解压的命令到 /usr/bin 目录 $ cp /root/docker/* /usr/bin # 创建 docker 组，否则会有 could not change group /var/run/docker.sock to docker: group docker not found 的警告信息，并且 cir-docker 会启动失败 $ groupadd docker # 编写启动文件 $ cat > /etc/systemd/system/docker.service <<"EOF" [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target EOF # 配置代理 $ mkdir -p /etc/systemd/system/docker.service.d cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF [Service] Environment="HTTP_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="HTTPS_PROXY=http://${PROXY_IP}:${PROXY_PORT}" Environment="NO_PROXY=localhost,127.0.0.1" EOF # 修改 cgroup 为 systemd，修改日志驱动 $ [ ! -d "/etc/docker" ] && mkdir /etc/docker cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" } } EOF # 重新加载配置 $ systemctl daemon-reload # 启动（重启） docker $ systemctl restart docker && systemctl enable docker # 查看代理、Cgroup 驱动、日志驱动配置 $ docker info | grep -E "Proxy|Cgroup Driver|Logging Driver" Logging Driver: json-file Cgroup Driver: systemd HTTP Proxy: http://192.168.230.1:10809 HTTPS Proxy: http://192.168.230.1:10809 No Proxy: localhost,127.0.0.11.3.2 安装 docker-compose# 创建插件目录 $ mkdir -p /usr/libexec/docker/cli-plugins # 定义要安装的 docker-compose 版本及架构（x86_64、aarch64） $ COMPOSE_VERSION=2.33.0; COMPOSE_ARCH=x86_64 # 从官方仓库下载二进制 docker-compose 命令 $ wget https://github.com/docker/compose/releases/download/v"${COMPOSE_VERSION}"/docker-compose-linux-"${COMPOSE_ARCH}" -P /root # 安装 docker-compose $ install -m 755 /root/docker-compose-linux-"${COMPOSE_ARCH}" /usr/libexec/docker/cli-plugins/docker-compose # 验证 docker-compose 是否安装成功 $ docker compose version Docker Compose version v2.33.02 安装（卸载）ollama2.1 安装 ollama2.1.1 在线安装参考文档：ollama/docs/linux.md at main · ollama/ollama · GitHub# 安装 ollama（若不指定版本则安装最新版本） $ curl -fsSL https://ollama.com/install.sh | OLLAMA_VERSION=0.5.11 sh # 修改 ollama 监听地址，默认监听在回环网卡 $ sed -i '/^Environment=.*/i Environment="OLLAMA_HOST=0.0.0.0:11434"' /etc/systemd/system/ollama.service # 重新加载配置 $ systemctl daemon-reload # 重新启动 ollama $ systemctl restart ollama # 查看监听的地址 $ netstat -anpt | grep ollama tcp6 0 0 :::11434 :::* LISTEN 110562/ollama2.1.2 本地安装参考文档：ollama/docs/linux.md at main · ollama/ollama · GitHub# 指定要安装的 ollama 版本及架构（amd64、arm64） $ OLLAMA_VERSION=0.5.11; OLLAMA_ARCH=amd64 # 下载安装包 $ wget https://github.com/ollama/ollama/releases/download/v"${OLLAMA_VERSION}"/ollama-linux-"${OLLAMA_ARCH}".tgz -P /root # 解压并安装 $ tar -xvf /root/ollama-linux-"${OLLAMA_ARCH}".tgz -C /usr # 创建 ollama 用户、组 $ useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama usermod -a -G ollama $(whoami) # 编写 service 文件 $ cat > /etc/systemd/system/ollama.service <<EOF [Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment="OLLAMA_HOST=0.0.0.0:11434" Environment="PATH=$PATH" [Install] WantedBy=default.target EOF # 重载配置文件 $ systemctl daemon-reload # 启动 ollama 并设置开机自启 $ systemctl start ollama && systemctl enable ollama # 查看监听的地址 $ netstat -anpt | grep ollama tcp6 0 0 :::11434 :::* LISTEN 2650/ollama2.2 卸载 ollama# 停止 ollama 服务 $ systemctl stop ollama && systemctl disable ollama # 删除 service 文件 $ rm -rf /etc/systemd/system/ollama.service # 删除 ollama 二进制文件 $ rm -rf $(which ollama) # 删除 ollama 库文件 $ rm -rf /usr/local/lib/ollama # 删除 ollama 用户、组 $ groupdel ollama userdel ollama # 删除家目录（同时会删除家目录下的大模型文件） $ rm -rf /usr/share/ollama2.3 ollama 使用指南2.3.1 命令使用指南$ ollama Usage: ollama [flags] ollama [command] Available Commands: serve Start ollama # 启动 ollama 服务 create Create a model from a Modelfile # 从 Modelfile 文件创建模型 show Show information for a model # 显示模型信息 run Run a model # 运行模型，若不存在则先下载 stop Stop a running model # 停止正在运行的模型 pull Pull a model from a registry # 从仓库拉取模型 push Push a model to a registry # 推送模型到仓库 list List models # 列出所有模型 ps List running models # 列出正在运行的模型并查看资源消耗 cp Copy a model # 复制模型 rm Remove a model # 删除模型 help Help about any command # 查看命令帮助 Flags: -h, --help help for ollama # 查看命令帮助 -v, --version Show version information # 查看版本2.3.2 相关环境变量（1）OLLAMA_HOST：指定 ollama 服务的监听地址及端口参考文档：ollama/api/client.go at main · ollama/ollama · GitHub使用场景：ollama 服务默认监听地址为 127.0.0.1，需要从外部访问或调用 ollama 服务使用方法：指定监听的地址和端口 OLLAMA_HOST=0.0.0.0:11434（2）OLLAMA_NUM_PARALLEL：每个模型同时处理的并行请求的最大数量参考文档：ollama/docs/faq.md at main · ollama/ollama · GitHub使用场景：每个模型需要处理多个并发使用方法：默认值将根据可用内存自动选择 4 或 1，若有需要可以手动调整 OLLAMA_NUM_PARALLEL=10（3）OLLAMA_MAX_QUEUE：当 ollama 忙碌时，它在拒绝额外请求之前将排队的最大请求数量参考文档：ollama/docs/faq.md at main · ollama/ollama · GitHub使用场景：调整 ollama 忙碌时可以排队的最大请求数量使用方法： 默认值是 512，若有需要可以手动调整 OLLAMA_MAX_QUEUE=256（4）OLLAMA_MAX_LOADED_MODELS：可同时加载的最大模型数量参考文档：ollama/docs/faq.md at main · ollama/ollama · GitHub使用场景：同时需要加载多个模型（如果已加载一个或多个模型时，没有足够的可用内存来加载新的模型请求，所有新的请求将被排队，直到新模型能够被加载。当先前的模型变为闲置时，将卸载一个或多个模型以腾出空间给新模型。排队的请求将按顺序处理。在使用 GPU 推理时，新模型必须能够完全适应 VRAM，以允许并发加载模型。）使用方法：默认值为 CPU 或 GPU 的 3 倍，若有需要可以手动调整 OLLAMA_MAX_LOADED_MODELS=6（5）CUDA_VISIBLE_DEVICES：限制 ollama 可使用的 NVIDIA 显卡参考文档：ollama/docs/gpu.md at main · ollama/ollama · GitHub使用场景：系统中有多块 NVIDIA 显卡，需要限制 ollama 只使用其中一部分或完全不使用显卡使用方法：使用数字 ID：执行 nvidia-smi 命令获取显卡的序号，然后定义环境变量 CUDA_VISIBLE_DEVICES=0,1使用 UUID：执行 nvidia-smi -L 命令获取显卡 UUID，然后定义环境变量 CUDA_VISIBLE_DEVICES=GPU-1831a5ee-622a-7e65-06cc-d57de8902585,GPU-d21e966e-7a89-884f-d0b2-444d371bb8f9不使用显卡：若想忽略显卡并强制使用 CPU，可以使用一个无效的 GPU ID，例如 CUDA_VISIBLE_DEVICES=-13 安装（使用）Dify3.1 安装 Dify参考文档：Docker Compose 部署 | Dify# 克隆 Dify 源代码至本地环境 $ git clone https://github.com/langgenius/dify.git # 进入 Dify 源代码目录 $ cd dify # 切换到需要的版本 $ git checkout 0.15.3 # 进入 Dify 源代码的 Docker 目录 $ cd docker # 复制环境配置文件 $ cp .env.example .env # 启动 Docker 容器 $ docker compose up -d [+] Running 74/74 ✔ api Pulled 211.9s ✔ sandbox Pulled 213.7s ✔ redis Pulled 161.0s ✔ weaviate Pulled 8.8s ✔ worker Pulled 211.9s ✔ db Pulled 157.2s ✔ web Pulled 133.0s ✔ ssrf_proxy Pulled 83.6s ✔ nginx Pulled 19.2s [+] Running 11/11 ✔ Network docker_default Created 0.0s ✔ Network docker_ssrf_proxy_network Created 0.0s ✔ Container docker-web-1 Started 0.4s ✔ Container docker-sandbox-1 Started 0.3s ✔ Container docker-ssrf_proxy-1 Started 0.5s ✔ Container docker-redis-1 Started 0.3s ✔ Container docker-weaviate-1 Started 0.4s ✔ Container docker-db-1 Started 0.4s ✔ Container docker-api-1 Started 0.5s ✔ Container docker-worker-1 Started 0.6s ✔ Container docker-nginx-1 Started 0.7s # 查看 3 个业务服务 api/worker/web，以及 6 个基础组件 weaviate/db/redis/nginx/ssrf_proxy/sandbox 是否运行 $ docker compose ps在 Windows 浏览器中访问 http://${your_server_ip}/install 进入管理员初始化页面，设置管理员账户在 Windows 浏览器中访问 http://${your_server_ip} 进入主页面
本文基于 openEuler 22.03 LTS SP1 操作系统进行操作1 VNC 部署流程1.1 安装 VNC# 安装 VNC 服务端 $ yum install -y tigervnc-server # 安装 VNC 客户端（可选） $ yum install -y tigervnc # 查看安装情况 $ rpm -qa | grep tigervnc tigervnc-selinux-1.12.0-9.oe2203sp1.noarch tigervnc-license-1.12.0-9.oe2203sp1.noarch tigervnc-server-minimal-1.12.0-9.oe2203sp1.x86_64 tigervnc-server-1.12.0-9.oe2203sp1.x86_64 tigervnc-1.12.0-9.oe2203sp1.x86_64 # 查看服务管理文件，用于使用 systemd 管理 VNC 服务 $ ll /usr/lib/systemd/system/vncserver\@.service -rw-r--r-- 1 root root 1558 5月 24 2023 /usr/lib/systemd/system/vncserver@.service # 查看相关配置文件 $ tree /etc/tigervnc/ /etc/tigervnc/ ├── vncserver-config-defaults # 默认配置文件，可被 ~/.vnc/config 和 vncserver-config-mandatory 覆盖 ├── vncserver-config-mandatory # 强制配置文件，可以覆盖 ~/.vnc/config 和 vncserver-config-defaults └── vncserver.users # 配置 VNC 用户以及访问端口号 0 directories, 3 files1.2 配置 tigervnc-server1.2.1 修改默认配置文件tigervnc-server 默认配置文件位于 /etc/tigervnc/vncserver-config-defaults 修改前的配置文件内容为：$ cat /etc/tigervnc/vncserver-config-defaults ## Default settings for VNC servers started by the vncserver service # # Any settings given here will override the builtin defaults, but can # also be overriden by ~/.vnc/config and vncserver-config-mandatory. # # See HOWTO.md and the following manpages for more details: # vncsession(8) Xvnc(1) # # Several common settings are shown below. Uncomment and modify to your # liking. # session=gnome # securitytypes=vncauth,tlsvnc # geometry=2000x1200 # localhost # alwaysshared修改后的配置文件内容为：$ cat /etc/tigervnc/vncserver-config-defaults session=gnome # 会话类型：gnome、dde、kiran securitytypes=vncauth,tlsvnc # 安全类型 geometry=1918x888 # VNC 界面分辨率，根据实际情况调整 # localhost # 若取消注释，表示只能在本地连接 VNC alwaysshared # 表示同一个显示端口允许多用户同时登录1.2.2 配置 VNC 用户及访问端口VNC 用户以及访问端口号配置文件为 /etc/tigervnc/vncserver.users# 修改配置文件，添加端口号及对应的用户名 $ sed -i '$a :1=root' /etc/tigervnc/vncserver.users说明：:1=root ：表示可以通过 :1 或 5901 端口，使用 root 用户登录 VNC，其他用户类似1.2.3 修改 VNC 用户密码（1）若 VNC 用户为 root 用户，则按照以下步骤设置 root 用户密码# 确认当前登录用户为 root 用户 $ whoami root # 设置 root 用户密码 $ vncpasswd Password: Verify: Would you like to enter a view-only password (y/n)? A view-only password is not used # 查看生成的密码文件 $ ls -l ~/.vnc/passwd -rw------- 1 root root 8 3月 4 14:18 /root/.vnc/passwd（2）若 VNC 用户为普通用户（假如普通用户为 ep），则按照以下步骤设置普通用户密码# 切换到 ep 用户 $ su - ep # 确认当前用户为 ep 用户 $ whoami ep # 设置 ep 用户密码 $ vncpasswd Password: Verify: Would you like to enter a view-only password (y/n)? A view-only password is not used # 查看生成的密码文件 $ ls -l ~/.vnc/passwd -rw------- 1 ep ep 8 3月 4 14:22 /home/ep/.vnc/passwd1.2.4 配置启动参数（可选，一般不需要）启动参数文件位于 ~/.vnc/xstartup ，若此文件不存在，则手动创建即可注意：若 VNC 用户为 root 用户，则此文件位于 /root/.vnc/ 目录，若 VNC 用户为普通用户，则此文件位于 /home/USER/.vnc/ 目录其中，DISPLAY 变量的值应该为：从 /etc/tigervnc/vncserver.users 文件查找当前用户对应端口号（1）gnome 桌面使用如下配置$ cat > ~/.vnc/xstartup <<EOF #!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS #exec /etc/X11/xinit/xinitrc (sleep 5 && export DISPLAY=:1 && xfce4-session) & EOF（2）DDE 桌面使用如下配置$ cat > ~/.vnc/xstartup <<EOF #!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS exec /usr/bin/startdde EOF（3）Kiran 桌面使用如下配置$ cat > ~/.vnc/xstartup <<EOF #!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS exec /usr/bin/kiran-session-manager --session-type=kiran EOF1.2.5 创建服务管理脚本# 复制服务管理脚本，vncserver@:1.service，其中 @ 后面的数字与 /etc/tigervnc/vncserver.users 文件中的端口对应 $ cp -a /usr/lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:1.service # 重新加载服务管理脚本 $ systemctl daemon-reload # 启动 VNC 服务并设置开机自启 $ systemctl enable --now vncserver@:1.service # 查看服务状态 $ systemctl status vncserver@:1.service ● vncserver@:1.service - Remote desktop service (VNC) Loaded: loaded (/etc/systemd/system/vncserver@:1.service; enabled; vendor preset: disabled) Active: active (running) since Fri 2024-03-01 15:22:13 CST; 1h 31min ago Process: 1195 ExecStart=/usr/libexec/vncsession-start :1 (code=exited, status=0/SUCCESS) Main PID: 1219 (vncsession) Tasks: 0 (limit: 98697) Memory: 1.8M CGroup: /system.slice/system-vncserver.slice/vncserver@:1.service ‣ 1219 /usr/sbin/vncsession root :1 3月 01 15:22:13 localhost systemd[1]: Starting Remote desktop service (VNC)... 3月 01 15:22:13 localhost systemd[1]: Started Remote desktop service (VNC). # 查看端口号 $ netstat -anpt | grep Xvnc tcp 0 0 0.0.0.0:5901 0.0.0.0:* LISTEN 1446/Xvnc tcp6 0 0 :::5901 :::* LISTEN 1446/Xvnc1.3 使用 noVNC 转发# 安装 noVNC 服务 $ yum install -y novnc # 连接 VNC，执行该命令后将持续占用终端 $ novnc_server --listen 44944 --vnc localhost:5901 # 可以执行以下命令，将其放入后台运行 $ nohup novnc_server --listen 44944 --vnc localhost:5901 & # 查看端口号 $ netstat -anpt | grep python3 tcp 0 0 0.0.0.0:44944 0.0.0.0:* LISTEN 9690/python3当然也可以编写 service 文件，使用 systemd 管理：# 编写 service 文件 $ cat > /etc/systemd/system/noVNC.service <<EOF [Unit] Description=noVNC Web VNC Proxy After=network.target [Service] Type=simple User=nobody ExecStart=/usr/bin/novnc_server --listen 44944 --vnc localhost:5901 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF # 重新加载配置 $ systemctl daemon-raload # 启动 noVNC 服务并设置开机自启 $ systemctl enable --now noVNC现在可以在 Windows 浏览器中通过 http://SERVER-IP:noVNC-PORT 来访问 VNC 服务了，例如：http://192.168.230.250:44944/
1 前言everything 镜像中包含了许多 rpm 包，可以提供基本的安装使用，然而还有一部分软件包需要连网到公网 repo 源中下载。但是在生产环境中，服务器大多数是不能连接公网的，因此需要搭建一个局域网 repo 源，即让一台能够连接公网的服务器从公网 repo 源中同步 rpm 包到本地，然后局域网的其他服务器再从这台能连接公网的服务器中下载 rpm 包2 所需的服务或命令2.1 Web 服务用于局域网中其他服务器访问，可以使用 httpd 服务或 nginx 服务2.2 dnf reposync 命令$ dnf reposync [OPTIONS] -c [CONFIG FILE] 指定配置文件运行（默认配置文件是 /etc/yum.conf） -q 安静操作 -v 显示详细信息 -b 尝试使用最佳的软件包版本 -C 完全从系统缓存运行，不更新缓存 -R [minutes] 最大命令等待时间 -y 所有问题自动回答 yes --assumeno 所有问题自动回答 no --enablerepo [repo] 启用其他存储库，可以指定多次 --disablerepo [repo] 禁用仓库，可以指定多次 --repo [repo], --repoid [repo] 仅使用指定的存储库 --exclude [package] 排除软件包 --forcearch ARCH 强制使用指定的架构 --arch [arch] 仅下载指定架构的软件包 --delete 删除存储库中不再存在的本地软件包 -n 仅下载最新的软件包 -p DOWNLOAD_PATH 指定软件包下载的位置 --norepopath 在下载目录中不重新生成以 `repo name` 命名的目录2.3 createrepo 命令$ createrepo [OPTION?] <directory_to_index> -q 以安静模式运行 -v 显示详细信息 -o 指定生成的元数据存放的位置 --excludes=PACKAGE_NAME_GLOB 指定生成元数据时排除的包 --update 在原有元数据上升级，只更新有变化的软件 --workers 读取 rpm 包的数量，默认为 53 同步官方源服务器名称用途操作系统版本IP 地址Server搭建局域网 repo 源openEuler 22.03 LTS SP1192.168.255.221Client模拟局域网内主机openEuler 22.03 LTS192.168.255.2203.1 Server 端配置3.1.1 系统基本设置# 关闭防火墙，并停止开机自启 $ systemctl stop firewalld $ systemctl disable firewalld # 关闭 SELinux $ setenforce 0 # 安装用于提供 reposync 命令的工具包 $ yum install -y dnf-plugins-core # 安装用于提供 createrepo 命令的工具包 $ yum install -y createrepo # 创建专用目录，保存同步的 RPM 包 $ mkdir /openEuler-22.03-LTS-REPO另外注意要留有足够的分区空间去保存 RPM 包3.1.2 配置 Web 服务此处使用 nginx 服务# 安装 nginx $ yum install -y nginx # 启动服务，并设置开机自启 $ systemctl start nginx $ systemctl enable nginx # 在默认网页根目录下创建 openEuler-22.03-LTS 目录及以下子目录，用来存放 RPM 包 $ mkdir -p /usr/share/nginx/html/openEuler-22.03-LTS/{everything,update,EPOL} $ mkdir -p /usr/share/nginx/html/openEuler-22.03-LTS/EPOL/main # 编写配置文件，允许显示目录索引 $ cat > /etc/nginx/conf.d/openEuler-22.03-LTS.conf <<EOF server { listen 8001; root /usr/share/nginx/html/openEuler-22.03-LTS; location / { autoindex on; autoindex_exact_size off; autoindex_format html; autoindex_localtime on; } } EOF # 重启 nginx 服务 $ systemctl restart nginx使用 Windows 浏览器访问 http://192.168.255.221:8001，查看访问是否正常3.1.3 配置 repo 源Server 端需要配置局域网内客户端主机操作系统的 repo 源。例如本实验中作为局域网 repo 源服务器的 Server 端的操作系统版本为 openEuler 22.03 LTS SP1，而客户端主机操作系统为 openEuler 22.03 LTS，那么需要在 Server 端配置 openEuler 22.03 LTS 操作系统的 repo 源openEuler 各版本的 repo 源可以在论坛中找到：【汇总贴】openEuler常用repo源 - 迁移 - openEuler 论坛注意：一定要修改新添加的 repo 源的 repo id 和 repo name，即修改 [ REPO ID ] 和 naem=REPO NAME 的内容，否则可能会和现有的 repo 源名字冲突# 在 Server 端配置客户端主机操作系统的 reop 源 $ cat > /etc/yum.repos.d/openEuler-22.03-LTS.repo <<EOF [openEuler-22.03-everything] name=openEuler-22.03-everything baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/x86_64/ enabled=1 gpgcheck=0 gpgkey=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/everything/x86_64/RPM-GPG-KEY-openEuler [openEuler-22.03-EPOL] name=openEuler-22.03-EPOL baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-22.03-update] name=openEuler-22.03-update baseurl=http://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS/update/x86_64/ enabled=1 gpgcheck=0 EOF # 清空 yum 缓存 $ yum clean all # 重建 yum 缓存 $ yum makecache # 查看当前的 repo 源 $ yum repolist repo id repo name openEuler-22.03-EPOL openEuler-22.03-EPOL openEuler-22.03-everything openEuler-22.03-everything openEuler-22.03-update openEuler-22.03-update从命令返回结果看到，openEuler 22.03 LTS 版本的 repo 源已经成功添加，另外需要记住此处的 repo id ，在同步时会指定 --repoid=REPO_ID 选项3.1.4 同步 everything 源（1）同步 everything 源的 RPM 包到本地# 同步 everything 源的 RPM 包到本地 $ dnf reposync -v --repoid=openEuler-22.03-everything -p /openEuler-22.03-LTS-REPO # 同步完成后会在 /openEuler-22.03-LTS-REPO 目录创建一个名称同 repo name 的目录 $ ls /openEuler-22.03-LTS-REPO/ openEuler-22.03-everything # 查看目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ └── Packages（2）生成 everything 源的 RPM 包元数据# 执行以下命令生成元数据 $ createrepo -v --workers 10 /openEuler-22.03-LTS-REPO/openEuler-22.03-everything # 查看生成元数据后的目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ ├── Packages └── repodata # 查看生成的元数据文件 $ ls /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/repodata 0079e1d3bd752a19486cb91269c98c8b5a6254d3ca13e5c0326e085561f1ed2a-other.sqlite.bz2 355628d38b0cd6163757264bc7971f3d86ff1d530a44c034786f3116b167f490-filelists.xml.gz 73565b368f50f6d2bb92543e2f7bcef4a9bc159ccdfbc728fc22e9b2ed5bb528-primary.xml.gz 7c20d73494e2525944a113b55983be13ba437e354da3e45f19f456b8f39457b4-other.xml.gz 9b353c421ef03be739e96d529e92393dfc4864205d974309a6af813e47893fff-filelists.sqlite.bz2 bd6c1976aae37a44ef7c7f9390c0321b4f7a27c4991e318f57b9c37016cb32fa-primary.sqlite.bz2 repomd.xml（3）创建软链接到 nginx 网页根目录# 创建 everything 源软链接到 nginx 网页根目录 $ ln -s /openEuler-22.03-LTS-REPO/openEuler-22.03-everything/ /usr/share/nginx/html/openEuler-22.03-LTS/everything/x86_643.1.5 同步 update 源（1）同步 update 源的 RPM 包到本地# 同步 update 源的 RPM 包到本地 $ dnf reposync -v --repoid=openEuler-22.03-update -p /openEuler-22.03-LTS-REPO # 同步完成后会在 /openEuler-22.03-LTS-REPO 目录创建一个名称同 repo name 的目录 $ ls /openEuler-22.03-LTS-REPO/ openEuler-22.03-update # 查看目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-update/ /openEuler-22.03-LTS-REPO/openEuler-22.03-update/ └── Packages（2）生成 update 源的 RPM 包元数据# 执行以下命令生成元数据 $ createrepo -v --workers 10 /openEuler-22.03-LTS-REPO/openEuler-22.03-update # 查看生成元数据后的目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-update /openEuler-22.03-LTS-REPO/openEuler-22.03-update ├── Packages └── repodata # 查看生成的元数据文件 $ ls /openEuler-22.03-LTS-REPO/openEuler-22.03-update/repodata 8943580f5aefe7f532fbbd9f19d771aaf9407a855b0acad33723007d8dde4199-primary.xml.gz ad1a113f7358bfebf9d13783d8fa8ce0a9b151725ecfc2da059226280422c30a-other.xml.gz bf573c34d9f77a76757a2a496b2c9ee671dddc81d660a95b063f8b81b8d7a4f9-filelists.sqlite.bz2 c6b747c4c6ee6cb6a44683b4a3636066cba5c9e573ea19ad95a5e315a9af1836-primary.sqlite.bz2 e152e3b11a7fcf011e16a27f7e6ba855ac12025b114ec5916e09d4edb0fa61e9-other.sqlite.bz2 f88eb68a9e41086c6b2de992367613c9b1e530bea82a73aa82e6faad6e5ed53d-filelists.xml.gz repomd.xml（3）创建软链接到 nginx 网页根目录# 创建 update 源软链接到 nginx 网页根目录 $ ln -s /openEuler-22.03-LTS-REPO/openEuler-22.03-update/ /usr/share/nginx/html/openEuler-22.03-LTS/update/x86_643.1.6 同步 EPOL 源（1）同步 EPOL 源的 RPM 包到本地# 同步 update 源的 RPM 包到本地 $ dnf reposync -v --repoid=openEuler-22.03-EPOL -p /openEuler-22.03-LTS-REPO # 同步完成后会在 /openEuler-22.03-LTS-REPO 目录创建一个名称同 repo name 的目录 $ ls /openEuler-22.03-LTS-REPO/ openEuler-22.03-EPOL # 查看目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL/ └── Packages（2）生成 EPOL 源的 RPM 包元数据# 执行以下命令生成元数据 $ createrepo -v --workers 10 /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL # 查看生成元数据后的目录结构 $ tree -L 1 /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL ├── Packages └── repodata # 查看生成的元数据文件 $ ls /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL/repodata 2d41ed62331b529104c7b04fd34680e8eeb8783e212e910e5230daaa66a900a4-filelists.sqlite.bz2 3445b86e5fd0157d0fd08aaf06cde6f1feca76517b574d8fdd3b40abe827b71e-other.xml.gz 709755e7d41e355645979f47b78155234bae9d50b2422105a4b03fca6ea93c83-filelists.xml.gz 70e673639de7efb802e65a54ce80e99c49ea93b1a8a4b4a676a47a91cadc99fa-primary.xml.gz 8c1cb6add3f18391a70436bed3bca18b9e0eac6861d8c5e2266c9952be3ea9f0-other.sqlite.bz2 bae172c52a64e4637d189780ff27d983e3c97bcbc17278f74afe0a23ab6e9ecd-primary.sqlite.bz2 repomd.xml（3）创建软链接到 nginx 网页根目录# 创建 EPOL 源软链接到 nginx 网页根目录 $ ln -s /openEuler-22.03-LTS-REPO/openEuler-22.03-EPOL/ /usr/share/nginx/html/openEuler-22.03-LTS/EPOL/main/x86_643.1.7 在前端界面查看 RPM 包使用 Windows 浏览器访问： http://192.168.255.221:8001，查看 RPM 包3.2 Client 端配置3.2.1 系统基本设置# 关闭防火墙，并停止开机自启 $ systemctl stop firewalld $ systemctl disable firewalld # 关闭 SELinux $ setenforce 03.2.2 配置 repo 源# 创建备份目录，将现有的 repo 源都移动到备份目录中 $ cd /etc/yum.repos.d/ $ mkdir bak $ mv ./* bak/ # 编写新的 repo 源，URL 地址指向局域网 repo 源服务器 cat > /etc/yum.repos.d/lan.repo <<EOF [openEuler-22.03-everything] name=openEuler-22.03-everything baseurl=http://192.168.255.221:8001/everything/x86_64/ enabled=1 gpgcheck=0 [openEuler-22.03-EPOL] name=openEuler-22.03-epol baseurl=http://192.168.255.221:8001/EPOL/main/x86_64/ enabled=1 gpgcheck=0 [openEuler-22.03-update] name=openEuler-22.03-update baseurl=http://192.168.255.221:8001/update/x86_64/ enabled=1 gpgcheck=0 EOF # 清空 yum 缓存 $ yum clean all # 重建 yum 缓存 $ yum makecache # 查看当前的 repo 源 $ yum repolist repo id repo name openEuler-22.03-EPOL openEuler-22.03-epol openEuler-22.03-everything openEuler-22.03-everything openEuler-22.03-update openEuler-22.03-update3.2.3 测试 repo 源# 随便搜索一个软件包 $ yum provides tree Last metadata expiration check: 0:08:11 ago on Wed 13 Dec 2023 04:36:36 PM CST. tree-1.8.0-2.oe2203.x86_64 : Tree file viewer tool Repo : openEuler-22.03-everything Matched from: Provide : tree = 1.8.0-2.oe2203 # 安装搜索的软件包 $ yum install -y tree4 使用 .iso 镜像搭建本地 repo 源4.1 基于 HTTP 协议搭建# 安装 httpd 服务及其他工具 $ yum install -y httpd createrepo # 修改配置文件，不显示默认网页 $ mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.bak $ sed -i '/^\s*DirectoryIndex/ s/index.html//' /etc/httpd/conf/httpd.conf # 挂载 everything 镜像 $ mount /dev/sr0 /mnt/ # 创建 repo 目录 $ mkdir -p /var/www/html/openEuler-LTS-SP1/Package # 从镜像中复制软件包到 repo 目录 $ cp /mnt/Packages/* /var/www/html/openEuler-LTS-SP1/Package/ # 生成元数据信息 $ createrepo -v --workers 20 /var/www/html/openEuler-LTS-SP1/ # 修改目录及文件权限 $ chmod 755 /var/www/html/openEuler-LTS-SP1/Package/ $ chmod 755 /var/www/html/openEuler-LTS-SP1/repodata/ $ chmod 644 /var/www/html/openEuler-LTS-SP1/Package/* $ chmod 644 /var/www/html/openEuler-LTS-SP1/repodata/* # 启动 httpd 服务 $ systemctl start httpd客户端编写 repo 文件：# 编写 repo 文件 $ cat > /etc/yum.repos.d/local.repo <<EOF [local-repo] name=local-repo baseurl=http://192.168.230.201/openEuler-LTS-SP1/ enabled=1 gpgcheck=0 EOF4.2 基于 FTP 协议搭建# 安装 vsftpd 服务及其他工具 $ yum install -y vsftpd createrepo # 配置 vsftpd 服务，允许匿名用户登录 $ sed -i '/^anonymous_enable/c anonymous_enable=YES' /etc/vsftpd/vsftpd.conf # 挂载 everything 镜像 $ mount /dev/sr0 /mnt/ # 创建 repo 目录 $ mkdir -p /var/ftp/pub/openEuler-22.03-LTS-SP1/Packages # 从镜像中复制软件包到 repo 目录 $ cp /mnt/Packages/* /var/ftp/pub/openEuler-22.03-LTS-SP1/Packages/ # 生成元数据信息 $ createrepo -v --workers 20 /var/ftp/pub/openEuler-22.03-LTS-SP1/ # 启动 vsftpd 服务 $ systemctl start vsftpd客户端编写 repo 文件：# 编写 repo 文件 $ cat > /etc/yum.repos.d/local.repo <<EOF [local-repo] name=local-repo baseurl=ftp://192.168.230.201/pub/openEuler-22.03-LTS-SP1/ enabled=1 gpgcheck=0 EOF
openEuler 操作系统用户权限管理——sudo 权限的授予与限制案例
说明：本文旨在分享记录在 openEuler 操作系统中，如何对普通用户进行权限授予与限制所有操作演示基于 openEuler 22.03 LTS SP1 版本汇总多种权限授予与限制的案例1 sudo 权限本节内容摘自官方文档：管理用户和用户组 (openeuler.org)使用 sudo 命令可以允许普通用户执行管理员帐户才能执行的命令sudo 命令允许已经在 /etc/sudoers 文件中指定的用户运行管理员帐户命令。例如，一个已经获得许可的普通用户可以运行如下命令：sudo /usr/sbin/useradd newuserl/etc/sudoers 的配置行如下所示：空行或注释行（以 # 字符打头）：无具体功能的行可选的主机别名行：用来创建主机列表的简称。必须以 Host_Alias 关键词开头，列表中的主机必须用逗号（,）隔开，如：Host_Alias FILESERVERS = fs1, fs2可选的用户别名行：用来创建用户列表的简称。用户别名行必须以 User_Alias 关键词开头，列表中的用户名必须以逗号（,）隔开。其格式同主机别名行:User_Alias ADMINS = jsmith, mikem可选的命令别名行：用来创建命令列表的简称。必须以 Cmnd_Alias 开头，列表中的命令必须用逗号（,）隔开：Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall可选的运行方式别名行：用来创建用户列表的简称。不同的是，使用这样的别名可以告诉 sudo 程序以列表中某一用户的身份来运行程序必要的用户访问说明行：user host=[ run as user ] command list以上字段的含义及说明如下表所示：字段含义说明user要授予 sudo 权限的用户指定一个真正的用户名或定义过的别名host该用户可以在哪个主机上执行命令指定一个真正的主机名或者定义过的主机别名run as user该用户以什么身份执行命令默认情况下，sudo 执行的所有命令都是以 root 身份执行command list该用户可以执行哪些命令可以是以逗号（,）分隔的命令列表，也可以是一个已经定义过的别名说明：可以在一行定义多个别名，中间用冒号 (:) 隔开可在命令或命令别名之前加上感叹号 (!)，使该命令或命令别名无效有两个关键词：ALL 和NOPASSWD。ALL 意味着“所有”（所有文件、所有主机或所有命令），NOPASSWD 意味着不用密码通过修改用户访问，将普通用户的访问权限修改为同 root 一样，则可以给普通用户分配特权对于 /etc/sudoers 文件的修改，推荐使用 visudo 命令，能够在保存时检查语法是否有误/etc/sudoers 文件预先添加了一个用户（root）和一个用户组（wheel）：## Allow root to run any commands anywhere root ALL=(ALL) ALL ## Allows people in group wheel to run all commands %wheel ALL=(ALL) ALL基于以上知识，可以实现对普通用户各种各样的授权与限制2 案例汇总2.1 案例一目标：授予普通用户创建用户，并修改用户密码的权限，但是禁止该用户修改 root 用户密码在 /etc/sudoers 文件中添加以下内容：user1 ALL=(ALL) /usr/sbin/useradd, /usr/bin/passwd, !/usr/bin/passwd "", !/usr/bin/passwd root配置说明：/usr/bin/useradd ：允许 user1 用户执行 useradd USER 命令创建普通用户/usr/bin/passwd ：允许 user1 用户执行 passwd USER 命令修改用户密码!/usr/bin/passwd root ：禁止 user1 用户执行 passwd root 命令修改 root 用户密码!/usr/bin/passwd "" ：禁止 user1 用户执行 passwd 命令修改 root 用户密码，因为 passwd 命令后边为空则默认为 root 用户效果演示：2.2 案例二目标：授予普通用户执行任何命令的权限方法一：可以将普通用户加入 wheel 组$ usermod -a -G wheel user1 $ id user1 uid=1000(user1) gid=1000(user1) groups=1000(user1),10(wheel)方法二：在 /etc/sudoers 文件添加以下内容user1 ALL=(ALL) ALL这两种方法的授权结果是有差异的，例如使用 su 命令的权限不同：将普通用户加入 wheel 组后，在该用户密码强度足够的前提下，该用户可以直接使用 su - 或 su - root 命令切换到 root 用户，而不必使用 sudo su - 或 sudo su - root 命令直接在 /etc/sudoers 文件中授予普通用户执行所有命令的权限后，该用户并不能直接使用 su - 或 su - root 命令切换到 root 用户，而必须要使用 sudo su - 或 sudo su - root 命令之所以出现这两种差异，是因为 /etc/pam.d/su 文件中有以下配置：auth required pam_wheel.so use_uid这一行配置的意思是：只允许只允许 root 用户和 wheel 群组的帐户使用 su 命令，限制其他帐户使用。openEuler 默认开启此配置，因此导致普通用户即使拥有执行所有命令的权限，也不能使用 su 命令2.3 案例三目标：授予普通用户执行任何命令的权限，但是禁止该用户切换到 root 用户在 /etc/sudoers 文件中添加以下内容：user1 ALL=(ALL) ALL, !/usr/bin/su - root, !/usr/bin/su - , !/usr/bin/bash配置说明：ALL ：允许 user1 用户执行所有命令!/usr/bin/su - root ：禁止 user1 用户执行 sudo su - root 命令切换到 root 用户!/usr/bin/su - ：禁止 user1 用户执行 sudo su - 命令切换到 root 用户，因为 su - 命令后边为空则默认为 root 用户!/usr/bin/bash ：禁止 user1 用户执行 sudo -i 、 sudo -i root 、 sudo /bin/bash 等方式切换到 root 用户效果演示：
xfs、ext4 文件系统都支持 LVM 逻辑卷缩容吗？如何对根分区缩容？
1 文件系统对缩容有无限制此节主要验证当前主流的 xfs 文件系统和 ext4 文件系统是否都支持 LVM 逻辑卷的缩容：验证按照目前众所周知的操作规范，缩容前先要卸载对应分区基于 openEuler 22.03 LTS SP1 操作系统进行验证（1）准备工作创建大小约为 25G 的卷组，后续基于此卷组创建逻辑卷# 创建大小约为 25G 的卷组（VG） $ vgcreate vg0 /dev/sdb Physical volume "/dev/sdb" successfully created. Volume group "vg0" successfully created # 查看创建的 VG 的详细信息 $ vgdisplay vg0 --- Volume group --- VG Name vg0 System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 1 Act PV 1 VG Size <25.00 GiB PE Size 4.00 MiB Total PE 6399 Alloc PE / Size 0 / 0 Free PE / Size 6399 / <25.00 GiB VG UUID PhStrz-y8do-kZAl-a9hq-dkdj-mqZl-TTqDMX1.1 xfs 文件系统 LVM 逻辑卷缩容（1）创建大小约为 10G 的逻辑卷，并格式化为 xfs 文件系统，进行挂载测试# 创建大小为 10G 的逻辑卷 lv_xfs $ lvcreate -L +10G -n lv_xfs vg0 Logical volume "lv_xfs" created. # 查看创建的逻辑卷的详细信息 $ lvdisplay /dev/vg0/lv_xfs --- Logical volume --- LV Path /dev/vg0/lv_xfs LV Name lv_xfs VG Name vg0 LV UUID W5YEDp-9kx3-JChe-MxLJ-1P06-yfF3-KTtlzD LV Write Access read/write LV Creation host, time localhost.localdomain, 2024-03-13 09:20:51 +0800 LV Status available # open 0 LV Size 10.00 GiB Current LE 2560 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:3 # 将此逻辑卷格式化为 xfs 文件系统 $ mkfs.xfs /dev/vg0/lv_xfs meta-data=/dev/vg0/lv_xfs isize=512 agcount=4, agsize=655360 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=1 inobtcount=1 data = bsize=4096 blocks=2621440, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # 挂载此逻辑卷，并查看挂载情况 $ mkdir /lv_xfs $ mount /dev/vg0/lv_xfs /lv_xfs/ $ df -Th /dev/vg0/lv_xfs Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/vg0-lv_xfs xfs 10G 104M 9.9G 2% /lv_xfs（2）将以上逻辑卷缩容至 5G，查看分区是否正常# 卸载分区挂载 $ umount /dev/vg0/lv_xfs # 将逻辑卷缩容 5G $ lvreduce -L 5G /dev/vg0/lv_xfs WARNING: Reducing active logical volume to 5.00 GiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce vg0/lv_xfs? [y/n]: y Size of logical volume vg0/lv_xfs changed from 10.00 GiB (2560 extents) to 5.00 GiB (1280 extents). Logical volume vg0/lv_xfs successfully resized. # 重新格式化，出现报错 $ xfs_growfs /dev/vg0/lv_xfs xfs_growfs: /dev/vg0/lv_xfs is not a mounted XFS filesystem # 强制挂载，出现报错 $ mount /dev/vg0/lv_xfs /lv_xfs/ mount: /lv_xfs: can't read superblock on /dev/mapper/vg0-lv_xfs.出现报错，不能重新格式化，不能强制挂载，说明 xfs 文件系统的缩容存在问题如果使用 mkfs.xfs -f 命令进行强制格式化，则可以正常缩容，但是分区上的所有数据也会丢失，这种操作显然是不行的# 使用 mkfs.xfs -f 命令进行强制格式化 $ mkfs.xfs -f /dev/vg0/lv_xfs meta-data=/dev/vg0/lv_xfs isize=512 agcount=4, agsize=327680 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=1 inobtcount=1 data = bsize=4096 blocks=1310720, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # 挂载，并查看分区大小 $ mount /dev/vg0/lv_xfs /lv_xfs/ $ df -Th /dev/vg0/lv_xfs Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/vg0-lv_xfs xfs 5.0G 68M 5.0G 2% /lv_xfs（3）结论xfs 文件系统不能进行 LVM 逻辑卷的缩容操作1.2 ext4 文件系统 LVM 逻辑卷缩容（1）创建大小约为 10G 的逻辑卷，并格式化为 ext4 文件系统，进行挂载测试# 创建大小为 10G 的逻辑卷 lv_xfs $ lvcreate -L +10G -n lv_ext4 vg0 Logical volume "lv_ext4" created. # 查看创建的逻辑卷的详细信息 $ lvdisplay /dev/vg0/lv_ext4 --- Logical volume --- LV Path /dev/vg0/lv_ext4 LV Name lv_ext4 VG Name vg0 LV UUID 0yVn8J-OiP7-M0SB-GWZG-qHTa-YOC4-k8JVEK LV Write Access read/write LV Creation host, time localhost.localdomain, 2024-03-13 10:36:01 +0800 LV Status available # open 0 LV Size 10.00 GiB Current LE 2560 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:4 # 将此逻辑卷格式化为 xfs 文件系统 $ mkfs.ext4 /dev/vg0/lv_ext4 mke2fs 1.46.4 (18-Aug-2021) Creating filesystem with 2621440 4k blocks and 655360 inodes Filesystem UUID: 3794e4d4-4cbf-4aaa-921c-1e7159edef07 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632 Allocating group tables: done Writing inode tables: done Creating journal (16384 blocks): done Writing superblocks and filesystem accounting information: done # 挂载此逻辑卷，并查看挂载情况 $ mkdir /lv_ext4 $ mount /dev/vg0/lv_ext4 /lv_ext4/ $ df -Th /dev/vg0/lv_ext4 Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/vg0-lv_ext4 ext4 9.8G 24K 9.3G 1% /lv_ext4（2）将以上逻辑卷缩容至 5G，查看分区是否正常# 卸载分区挂载 $ umount /dev/vg0/lv_ext4 # 进行磁盘检查（必须步骤） $ e2fsck -f /dev/vg0/lv_ext4 e2fsck 1.46.4 (18-Aug-2021) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information /dev/vg0/lv_ext4: 11/655360 files (0.0% non-contiguous), 66753/2621440 blocks # 缩容文件系统 $ resize2fs /dev/vg0/lv_ext4 5G resize2fs 1.46.4 (18-Aug-2021) Resizing the filesystem on /dev/vg0/lv_ext4 to 1310720 (4k) blocks. The filesystem on /dev/vg0/lv_ext4 is now 1310720 (4k) blocks long. # 回收逻辑卷空闲空间 $ lvreduce -L 5G /dev/vg0/lv_ext4 WARNING: Reducing active logical volume to 5.00 GiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce vg0/lv_ext4? [y/n]: y Size of logical volume vg0/lv_ext4 changed from 10.00 GiB (2560 extents) to 5.00 GiB (1280 extents). Logical volume vg0/lv_ext4 successfully resized. # 重新挂载，并查看挂载情况 $ mount /dev/vg0/lv_ext4 /lv_ext4/ $ df -Th /dev/vg0/lv_ext4 Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/vg0-lv_ext4 ext4 4.9G 24K 4.6G 1% /lv_ext4（3）结论ext4 文件系统可以进行 LVM 逻辑卷的缩容操作1.3 结论经过以上测试，得出结论：xfs 文件系统不能进行 LVM 逻辑卷的缩容操作，ext4 文件系统可以进行 LVM 逻辑卷的缩容操作另外，也可以通过另外一种缩容方式明确得出这一结论。即使用 lvreduce 命令的 -r 参数，此参数表示在缩容时同时使用 fsadm 调整底层文件系统的大小：$ man lvreduce ...... -r|--resizefs Resize underlying filesystem together with the LV using fsadm(8). ......（1）xfs 文件系统 LVM 逻辑卷缩容# 执行以下命令对 xfs 文件系统的 LVM 逻辑卷缩容 $ lvreduce -r -L 5G /dev/vg0/lv_xfs输出内容如下图所示：报错显示：Xfs filesystem shrinking is unsuppored（Xfs 文件系统收缩不被支持）（2）ext4 文件系统 LVM 逻辑卷缩容# 执行以下命令对 ext4 文件系统的 LVM 逻辑卷缩容 $ lvreduce -r -L 5G /dev/vg0/lv_ext4输出内容如下图所示： 信息显示逻辑卷缩容成功2 能否挂载状态缩容现有处于挂载状态的文件系统为 ext4 的逻辑卷：直接对其进行缩容操作，命令执行过程中会询问是否卸载分区：缩容后，会自动挂载分区：综上，不能对处于挂载状态的逻辑卷分区进行缩容操作，工具会自动卸载、挂载3 如何对根分区进行缩容由 2.2 得出结论，在对逻辑卷缩容时必须要先卸载分区。正常系统中，根分区显然是不能卸载的，那么想对根分区进行缩容该如何操作呢？进单用户模式进行操作，发现单用户模式并没有 lvm 相关命令正确的根分区缩容操作如下：（1）使用光盘进入救援模式，选择 “ 3) Skip to shell ”，这样可以不去挂载 /mnt/sysroot 或 /mnt/sysimage（2）执行 lsblk 命令查看逻辑卷是否处于激活状态，即是否有 /dev/mapper/... 相关路径，若没有则需要先激活逻辑卷（3）执行 vgchange -ay 命令激活所有卷组及其逻辑卷，之后再次执行 lsblk 命令查看逻辑卷路径（4）执行 lvreduce -r -L -20G /dev/mapper/openeuler-root 命令进行缩容操作，并验证缩容结果（5）退出救援模式，进入系统，验证缩容结果及系统有无异常至此，根分区成功缩容！