[Ansible] CentOS 6 Playbook 中“(libselinux-python) 未安装!”问题的解决方案

大家好,
我是系统解决方案部门的Naka,我偶尔会想吃沾面和意大利面。
错误“(libselinux-python) 未安装!”经常会遇到
此错误可能需要手动修复。
但是,当您有大量机器并且想要使用 Ansible 管理它们时,却不得不手动处理每一台机器,这很麻烦。
于是我想,“如果我们用 Ansible 来解决这个问题岂不是更容易吗?”,然后就写了一个 Playbook。
这次,我们将介绍并解释“解决 CentOS 6 中‘(libselinux-python) 未安装!’问题的 Playbook”。
介绍
- 我们不建议使用 CentOS 6。这只是
在您被迫使用 CentOS 6 的情况下的临时解决方案。 - 是一个不受支持的版本。
它仅作为临时解决方案,不建议使用。
基本原因
(libselinux-python) 未安装!
当使用会发生变化的模块时,例如文件操作模块,
- 完全禁用。并未
- 此外(*1) 未安装 libselinux-python 软件包(*2)
这是当……时发生的错误
*1. 如果禁用 SELinux,则不会出现此错误。
*2. Ansible 运行在 Python 上,因此 Python 需要能够与 SELinux 交互。
* 对于 Python 3,这需要使用“python3-libselinux”,但 CentOS 6 似乎并未普遍提供此库。
手动解答
# sudo yum install libselinux-python
如果在目标端安装“libselinux-python”,这个问题基本上就能得到解决。
* 对于 Python 3,请使用“python3-libselinux”
然而, CentOS 6 已停止维护 (EOL), 如果存储库保留默认设置, 则 yum 很可能无法工作。
在这种情况下,您需要使用 wget 和 rpm 从可用的存储库进行本地安装。
因此,跨多个环境进行人工响应是相当困难的。
问:为什么要修改战术手册?
A. 不仅仅是在使用 Ansible 之前需要预先进行手动操作很麻烦;
还很容易产生这样的想法:“既然需要手动操作,那我干脆所有事情都手动做”,这就违背了初衷。因此,“积极转向使用 Ansible 来可靠地完成任何工作”。我们的立场是
问:它与 CentOS 7 不兼容吗?
A. 我认为更明智的做法是将 Playbook 分开,并在包含/导入阶段进行判断/分支,以处理版本差异。
我当时在想是否要让它兼容,但它已经包含了一个在无法使用“yum”时的分支,这使得情况变得有点复杂。
仓库目录层次结构名称可能会根据操作系统版本而变化,这将进一步增加分支数量。
我们决定不在单个 Playbook 中包含版本分支,因为我们认为这会降低可读性和可维护性。
执行环境
■ Linux 环境
操作系统:AlmaLinux 8.5 版(WSL2 环境)
Shell:Bash
Docker:26.1.0,版本 9714adc■ Ansible 环境(WSL2 中的 Docker 容器)
操作系统:AlmaLinux 8.9 版
Ansible:Ansible-core 2.12.10■ Windows 环境
操作系统:Windows 11 专业版(版本:23H2)
语言设置:已更改为日语■ CentOS 6 环境(Vagrant + VirtualBox)
操作系统:CentOS 6.9 (bento / centos-6.9)
Vagrant:2.4.1
VirtualBox:7.0.18 r162988 (Qt5.15.2)
IP:192.168.33.15
Ansible 2.12 环境构建流程
但兼容的Ansible 版本 (2.12)我们将使用
在上一篇文章中,我们解释了如何构建 Ansible 2.12,请参考这篇文章。
剧本
在 CentOS 6 环境中运行 Playbook,在一开始就包含/导入某些组件,从而防止出现错误。确保主动用于旨在
当然,也可以在错误发生后使用此剧本来解决问题。
libselinux-python_wget.yml
此 Playbook 通过 `main.yml` 中的 `import_tasks` 加载。
(这是因为我倾向于按角色分离 Playbook,以提高可重用性、可读性和可维护性。)
--- ## 变量默认值 # wget_repo | default ("http://ftp.iij.ad.jp/pub/linux/centos-vault") - name: 检查 SELinux ansible.builtin.command: cmd: getenforce register: SELinux_result - ansible.builtin.debug: var: SELinux_result.stdout - name: 检查 libselinux-python ansible.builtin.shell: cmd: rpm -aq | grep libselinux-python register: rpm_result ignore_errors: yes - ansible.builtin.debug: var: rpm_result.stdout # 如果 SELinux 已禁用,Ansible 无需任何附加命令即可运行,因此不会执行此项。 # 此外,如果 libselinux-python 已安装,也不会执行此项。 - name: yum install libselinux-python ansible.builtin.yum: name: libselinux-python state: present register: yum_libselinux_result ignore_errors: yes when: not ( SELinux_result.stdout is search("disabled") ) and not ( rpm_result.stdout is search("libselinux-python*")) # 如果使用 yum 安装失败,则使用 wget 安装 - name: Setup libselinux-python when: yum_libselinux_result is failed and not ( rpm_result.stdout is search("libselinux-python*")) block: # 由于软件包名称会根据版本而变化,因此将软件包列表的 HTML 存储在一个变量中 -name: Get OS_version Packages ansible.builtin.uri: url: "{{ wget_repo | default('http://ftp.iij.ad.jp/pub/linux/centos-vault') }}/{{ ansible_distribution_version }}/os/x86_64/Packages/" method: GET return_content: yes register: packages_content # 从 HTML 获取 "libselinux-python" 的 rpm 名称 - name: Extract rpm_name ansible.builtin.set_fact: rpm_name: "{{ packages_content.content | regex_search('libselinux-python-(.*?)\\.x86_64\\.rpm') }}" - ansible.builtin.debug: var: rpm_name # 使用获取的 rpm 名称下载 - name: Download libselinux-python ansible.builtin.get_url: url: "{{ wget_repo | default('http://ftp.iij.ad.jp/pub/linux/centos-vault') }}/{{ ansible_distribution_version }}/os/x86_64/Packages/{{ rpm_name }}" dest: "/tmp/{{ rpm_name }}" # 在无法使用 yum 的情况下使用 rpm 安装 - name: 安装 libselinux-python ansible.builtin.command: rpm -ivh /tmp/"{{ rpm_name }}"
我已在评论中写明了我的大部分意图,但下面我将解释一下。
# wget_repo: | default ("http://ftp.iij.ad.jp/pub/linux/centos-vault")
如果无法使用 yum,请直接从存储库获取 libselinux-python:
使用变量指定要使用的存储库,但如果未指定变量,则在开头添加注释,明确说明所使用的存储库来自 IIJ。
- name:检查 SELinux
- name:检查 libeselinux-python
在 SELinux 被禁用的环境中,程序无需“libselinux-python”即可运行,因此无需该库。程序
首先检查 SELinux 的状态,然后将状态存储在一个变量中以供后续判断。
此外,考虑到 CentOS 6 可能不支持 yum,我们将通过 Shell 模块检查它是否已使用 rpm 安装。
此结果也会保存到一个变量中以供验证。
- name: yum install libselinux-python
SELinux 状态不是“已禁用”且未安装“libselinux-python”才会执行此命令
尝试使用 yum 模块进行安装,如果显示“已安装”或“已安装”,则说明安装成功。
如果“yum”运行失败,则进程会继续执行“ignore_errors: yes”,但任务失败的情况会记录在一个变量中以供检查,后续任务会尝试直接从存储库中检索数据。
- name:设置 libselinux-python
when:yum_libselinux_result 失败
block:
当通过“yum”安装失败时(满足条件),将执行此任务块。
它会直接从软件仓库检索软件包,并使用rpm进行安装。
首先,使用 ansible_facts 中的“ansible_distribution_version”从存储库的目录层次结构中获取与操作系统次版本匹配的“libselinux-python”的官方软件包名称,并将其保存为变量。
然后使用该变量通过 get_uri 模块下载它,并通过 command 模块使用 rpm 在本地安装它。
例子
用于验证环境的库存文件
虽然 CentOS 6 (bento / centos-6.9) 默认使用密码验证,但仍然存在使用密码验证的环境(不建议这样做),因此我们在这种状态下进行了测试。
-- all: vars: ansible_user: vagrant hosts: targetnode: ansible_host: 192.168.33.15 ansible_ssh_pass: vagrant
main.yml
我没有在 main.yml 中编写任务,而是采用了使用 import_tasks 导入 Playbook 的方式。
(这是因为我更喜欢按角色分离 Playbook,以提高代码的重用性、可读性和可维护性。)
- name: libselinux-python hosts: targetnode< become: yes vars: wget_repo: "http://ftp.iij.ad.jp/pub/linux/centos-vault" tasks - name: Include libselinux-python(wget) ansible.builtin.import_tasks: libselinux-python_wget.yml
剧本执行
在本文中,我们将使用较旧版本的 Ansible 在容器中运行它。
[root@author 的容器环境工作]# ansible-playbook -i hosts main.yml
最后
虽然很耗时,但我尝试使用 Ansible 实现一些标准化任务的自动化。
这意味着我可以多次重复使用这些工具,而且就熟悉 Ansible 而言,这也是一次很好的学习经历。
由于 CentOS 6 环境通常缺乏使用“yum”的能力,使得 Ansible 的实现面临很高的门槛,
我希望本文能够为读者探索 Ansible 提供一个起点,并提供一些有用的知识和信息。
感谢您阅读至此!
参考资料
ansible.builtin.yum 模块 – 使用 yum 包管理器管理软件包
https://docs.ansible.com/ansible/9/collections/ansible/builtin/yum_module.html
4
