1 相关知识在编译内核之前，首先了解内核启动及 grub 引导菜单的相关知识，了解如何设置修改默认启动内核以及引导菜单中缺失内核的解决方法（1）查看系统已安装的所有内核# 查看系统已安装的所有内核 $ ls /boot/vmlinuz-* /boot/vmlinuz-0-rescue-331f20b322834ebcbe73ee7e21382816 /boot/vmlinuz-6.6.8 /boot/vmlinuz-5.10.0-136.12.0.86.oe2203sp1.x86_64（2）查看安装的内核是否在 grub 引导菜单内# 查看安装的内核是否在 grub 引导菜单内 $ grep ^menuentry /boot/grub2/grub.cfg menuentry 'openEuler (6.6.8) 22.03 (LTS-SP1)' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.10.0-136.12.0.86.oe2203sp1.x86_64-advanced-dedd25d9-b873-4aff-a832-1594ba77be44' { menuentry 'openEuler (5.10.0-136.12.0.86.oe2203sp1.x86_64) 22.03 (LTS-SP1)' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.10.0-136.12.0.86.oe2203sp1.x86_64-advanced-dedd25d9-b873-4aff-a832-1594ba77be44' { menuentry 'openEuler (0-rescue-331f20b322834ebcbe73ee7e21382816) 22.03 (LTS-SP1)' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-331f20b322834ebcbe73ee7e21382816-advanced-dedd25d9-b873-4aff-a832-1594ba77be44' {若发现（1）中查找到的内核并没有出现在 grub.cfg 文件中，那么表明在系统启动时，grub 菜单中不会出现该内核选项，即不能启动该内核，此时需要重新生成 grub.cfg 配置文件# 执行以下命令重新生成 grub.cfg 配置文件 $ grub2-mkconfig -o /boot/grub2/grub.cfg # 重新生成配置文件后，查看安装的内核是否在 grub 引导菜单内 $ grep ^menuentry /boot/grub2/grub.cfg（3）设置默认启动内核① 通过内核文件路径设置默认启动内核# 执行以下命令查看默认启动内核 $ grubby --default-kernel /boot/vmlinuz-6.6.8 # 执行以下命令设置默认启动内核 $ grubby --set-default /boot/vmlinuz-5.10.0-136.12.0.86.oe2203sp1.x86_64 # 设置完成后，再次查看默认启动内核 $ grubby --default-kernel /boot/vmlinuz-5.10.0-136.12.0.86.oe2203sp1.x86_64② 通过内核索引设置默认启动内核# 查看当前所有可启动内核及在 grub 菜单中的索引顺序 $ grubby --info ALL index=0 kernel=/boot/vmlinuz-6.6.8 args="ro resume=/dev/mapper/openeuler-swap rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap cgroup_disable=files apparmor=0 crashkernel=512M" root=/dev/mapper/openeuler-root initrd=/boot/initramfs-6.6.8.img title=openEuler (6.6.8) 22.03 (LTS-SP1) index=1 kernel=/boot/vmlinuz-5.10.0-136.12.0.86.oe2203sp1.x86_64 args="ro resume=/dev/mapper/openeuler-swap rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap cgroup_disable=files apparmor=0 crashkernel=512M" root=/dev/mapper/openeuler-root initrd=/boot/initramfs-5.10.0-136.12.0.86.oe2203sp1.x86_64.img title=openEuler (5.10.0-136.12.0.86.oe2203sp1.x86_64) 22.03 (LTS-SP1) index=2 kernel=/boot/vmlinuz-0-rescue-331f20b322834ebcbe73ee7e21382816 args="ro resume=/dev/mapper/openeuler-swap rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap cgroup_disable=files apparmor=0 crashkernel=512M" root=/dev/mapper/openeuler-root initrd=/boot/initramfs-0-rescue-331f20b322834ebcbe73ee7e21382816.img title=openEuler (0-rescue-331f20b322834ebcbe73ee7e21382816) 22.03 (LTS-SP1) index=3 non linux entry index=4 non linux entry index=5 non linux entry # 通过索引序号设置默认启动内核 $ grubby --set-default-index=0 # 设置完成后，再次查看默认启动内核 $ grubby --default-kernel /boot/vmlinuz-6.6.8（4）initramfs 相关命令# 重新制作 initramfs $ dracut -f -a lvm --kver=$(uname -r) /boot/initramfs-$(uname -r).img # 将 initramfs 文件生成到其他位置 $ dracut -f --no-hostonly -output /root/initramfs-xxxx $(uname -r) # 将额外安装的驱动文件打入 initramfs $ dracut --no-hostonly --kver=$(uname -r) /boot/initramfs-$(uname -r).img # 查看 initramfs 文件 $ lsinitrd /boot/initramfs-$(uname -r).img # 解压 initramfs 文件 $ /usr/lib/dracut/skipcpio /boot/initramfs-$(uname -r).img | zcat | cpio -idmv # x2openEuler 检查 grubenv 文件 $ grub2-editenv /boot/grub2/grubenv set check=1 $ grub2-editenv /boot/grub2/grubenv unset check2 编译安装内核以下将以当前的最新的 6.6.8 版本内核为例，在 openEuler 22.03 LTS SP1 操作系统上进行演示2.1 准备工作（1）查看当前使用的系统版本及内核版本# 查看系统版本 $ cat /etc/openEuler-release openEuler release 22.03 (LTS-SP1) # 查看内核版本 $ uname -r 5.10.0-136.12.0.86.oe2203sp1.x86_64（2）安装依赖工具# 安装依赖工具 $ yum install -y \ gcc clang llvm binutils-devel make m4 flex bison patch rpm-build rsync \ audit-libs-devel elfutils-devel elfutils-libelf-devel libcap-devel libcap-ng-devel \ libunwind-devel libzstd-devel numactl-devel openssl-devel zlib-devel xz-devel \ ncurses-devel newt-devel pciutils-devel libbabeltrace-devel dwarves \ python3-devel python3-docutils perl-devel perl-generators \ java-1.8.0-openjdk java-1.8.0-openjdk-devel java-devel \ asciidoc xmlto \ gtk2-devel \ net-tools glibc-static2.2 下载新版本内核Linux 内核（内核补丁）官网：The Linux Kernel Archives# 下载内核 $ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.8.tar.xz -P /root --2023-12-21 15:52:44-- https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.8.tar.xz Resolving cdn.kernel.org (cdn.kernel.org)... 151.101.109.176, 2a04:4e42:1a::432 Connecting to cdn.kernel.org (cdn.kernel.org)|151.101.109.176|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 140076264 (134M) [application/x-xz] Saving to: ‘/root/linux-6.6.8.tar.xz’ linux-6.6.8.tar.xz 100%[==============================================>] 133.59M 22.7MB/s in 11s 2023-12-21 15:52:58 (12.7 MB/s) - ‘/root/linux-6.6.8.tar.xz’ saved [140076264/140076264] # 解压内核文件，并更改目录名称 $ tar -Jxvf /root/linux-6.6.8.tar.xz -C /usr/src/kernels/ $ mv /usr/src/kernels/linux-6.6.8 /usr/src/kernels/6.6.82.3 打内核补丁（可选）# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 下载补丁文件 $ wget wget https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.6.8.xz --2023-12-22 10:35:02-- http://wget/ Resolving wget (wget)... failed: Name or service not known. wget: unable to resolve host address ‘wget’ --2023-12-22 10:35:03-- https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.6.8.xz Resolving cdn.kernel.org (cdn.kernel.org)... 146.75.113.176, 2a04:4e42:8c::432 Connecting to cdn.kernel.org (cdn.kernel.org)|146.75.113.176|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 587540 (574K) [application/x-xz] Saving to: ‘patch-6.6.8.xz’ patch-6.6.8.xz 100%[==============================================>] 573.77K 317KB/s in 1.8s 2023-12-22 10:35:07 (317 KB/s) - ‘patch-6.6.8.xz’ saved [587540/587540] FINISHED --2023-12-22 10:35:07-- Total wall clock time: 4.5s Downloaded: 1 files, 574K in 1.8s (317 KB/s) # 根据补丁文件压缩类型解压补丁文件 $ xz -dv patch-6.6.8.xz # 打补丁 $ patch -p1 -i patch-6.6.82.4 生成内核配置文件生成内核配置文件时有两种方案：重新生成新的内核配置文件基于现有内核配置文件修改2.4.1 重新生成新的内核配置文件# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 清理以前编译的残留文件（可选） $ make mrproper # 执行以下命令修改并生成内核配置文件 $ make menuconfig执行 make menuconfig 命令后，会弹出如下界面，可以勾选需要的功能或模块[ ] ：按 Y 勾选，按 N 取消勾选< > ：按 M 勾选，按 N 取消勾选说明[ * ] ：表示将功能直接编译进内核中，随内核直接在内存中运行< M > ：表示将功能以模块的方式保存在 ROM 中，再调到内存中运行编辑完成后，点击 <Save>，弹出以下界面点击 Ok，在新弹出的界面中点击 <Exit> 回到初始界面；在初始界面点击 <Exit> 退出，配置文件便会生成# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 查看生成的配置文件 $ ls -l .config -rw-r--r-- 1 root root 230696 Dec 21 18:37 .config2.4.2 基于现有内核配置文件修改# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 复制已有内核配置文件 $ cp /boot/config-5.10.0-136.12.0.86.oe2203sp1.x86_64 ./ # 清理以前编译的残留文件（可选） $ make mrproper # 执行以下命令修改并生成内核配置文件 $ make menuconfig执行 make menuconfig 命令后，会弹出如下界面点击 <Load>，弹出以下界面，填写复制过来的配置文件名称点击 Ok 退出到初始界面，进行进一步修改[ ] ：按 Y 勾选，按 N 取消勾选< > ：按 M 勾选，按 N 取消勾选说明[ * ] ：表示将功能直接编译进内核中，随内核直接在内存中运行< M > ：表示将功能以模块的方式保存在 ROM 中，再调到内存中运行编辑完成后，点击 <Save>，弹出以下界面点击 Ok，在新弹出的界面中点击 <Exit> 回到初始界面；在初始界面点击 <Exit> 退出，配置文件便会生成# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 查看生成的配置文件 $ ls -l .config -rw-r--r-- 1 root root 230696 Dec 21 18:37 .config2.5 编译安装内核编译安装内核可以分为两种方式：编译源代码后，执行 make install 安装编译源代码为 rpm 包，使用 yum 安装说明这两种方式互不冲突，可以结合使用：即进行了内核源代码编译安装后，仍然可以在编译的基础上，重新编译为 rpm 包；或者直接编译为 rpm 包后，仍然可以直接执行 make modules_install 和 make install 安装2.5.1 编译后使用 make install 安装（1）编译内核编译非常耗时，建议在配置较高的机器上进行，且在 make 时使用 -j 参数指定使用多线程# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 开始编译 $ make -j 12（2）安装内核模块# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 执行以下命令安装内核模块 $ make modules_install -j 12 # 安装内核模块后，会在 /usr/lib/modules/ 目录下创建以内核名称命名的目录，用于存放内核模块 $ tree -L 1 /usr/lib/modules/6.6.8/ /usr/lib/modules/6.6.8/ ├── build -> /usr/src/kernels/6.6.8 ├── kernel ├── modules.alias ├── modules.alias.bin ├── modules.builtin ├── modules.builtin.alias.bin ├── modules.builtin.bin ├── modules.builtin.modinfo ├── modules.dep ├── modules.dep.bin ├── modules.devname ├── modules.order ├── modules.softdep ├── modules.symbols └── modules.symbols.bin（3）安装内核# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 执行以下命令安装内核 $ make install INSTALL /boot # 安装内核后，会在 /boot 目录产生内核相关文件 $ ls /boot/*6.6.8* /boot/initramfs-6.6.8.img # 初始化虚拟文件系统 /boot/System.map-6.6.8 # 记录内核中所有符号在内存中中的虚拟地址 /boot/vmlinuz-6.6.8 # 内核文件 # 查看新内核是否被添加到 grub 菜单中 $ grep ^menuentry.*6.6.8 /boot/grub2/grub.cfg menuentry 'openEuler (6.6.8) 22.03 (LTS-SP1)' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.10.0-136.12.0.86.oe2203sp1.x86_64-advanced-dedd25d9-b873-4aff-a832-1594ba77be44' {2.5.2 编译为 rpm 包使用 yum 安装内核编译完成后，除了执行 make install 安装外，还可以将源代码编译为 rpm 包，方便使用（1）编译源代码为 rpm 包# 进入源代码目录 $ cd /usr/src/kernels/6.6.8/ # 执行以下命令编译为 rpm 包 $ make binrpm-pkg -j 12 ...... Wrote: /usr/src/kernels/6.6.8/rpmbuild/RPMS/x86_64/kernel-headers-6.6.8-3.x86_64.rpm Wrote: /usr/src/kernels/6.6.8/rpmbuild/RPMS/x86_64/kernel-6.6.8-3.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.sQCOXi + umask 022 + cd /usr/src/kernels/6.6.8 + rm -rf /usr/src/kernels/6.6.8/rpmbuild/BUILDROOT/kernel-6.6.8-3.x86_64 + RPM_EC=0 ++ jobs -p + exit 0 # 编译完成后，查看生成的 rpm 包（保存在源代码所在目录下的 rpmbuild/RPMS/ 目录中） $ tree rpmbuild/ rpmbuild/ ├── BUILDROOT ├── RPMS │ └── x86_64 │ ├── kernel-6.6.8-3.x86_64.rpm │ └── kernel-headers-6.6.8-3.x86_64.rpm └── SRPMS（2）安装内核 rpm 包# 使用 yum 安装内核了 $ yum install -y rpmbuild/RPMS/x86_64/kernel-6.6.8-3.x86_64.rpm # 查看安装后的内核 $ ls /boot/vmlinuz-* /boot/vmlinuz-0-rescue-331f20b322834ebcbe73ee7e21382816 /boot/vmlinuz-6.6.8 /boot/vmlinuz-5.10.0-136.12.0.86.oe2203sp1.x86_64 # 查看安装的内核模块 $ tree -L 1 /usr/lib/modules/6.6.8/ /usr/lib/modules/6.6.8/ ├── kernel ├── modules.alias ├── modules.alias.bin ├── modules.builtin ├── modules.builtin.alias.bin ├── modules.builtin.bin ├── modules.builtin.modinfo ├── modules.dep ├── modules.dep.bin ├── modules.devname ├── modules.order ├── modules.softdep ├── modules.symbols └── modules.symbols.bin # 查看新内核是否被添加到 grub 菜单中 $ grep ^menuentry.*6.6.8 /boot/grub2/grub.cfg menuentry 'openEuler (6.6.8) 22.03 (LTS-SP1)' --class openeuler --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-5.10.0-136.12.0.86.oe2203sp1.x86_64-advanced-dedd25d9-b873-4aff-a832-1594ba77be44' {3 启动测试首先确认安装的新内核是否为默认启动内核# 执行以下命令查看默认启动内核 $ grubby --default-kernel /boot/vmlinuz-6.6.8确认默认启动内核是安装的新内核后，重启系统，新内核正常出现在引导菜单中进入系统，进一步查看内核版本信息# 查看内核版本信息 $ uname -r 6.6.8
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 加密的目的
使用 x2openEuler 工具升级 SUSE12 过程中升级前检查中断的可能原因及解决方案
一、问题现象近期，遇到多起 SUSE12 升级过程中升级前检查中断的事件，具体报错现象如下图所示：经查看日志，发现是在收集硬件信息时报错，即 x2openEuler-client hardware-collect 命令执行失败：进一步查看升级日志，并且在待升级节点手动执行 x2openEuler-client hardware-collect 命令，均发现以下报错信息：报错显示：操作系统上没有发现 /usr/sbin/lspci 命令二、原因分析以上报错由一系列原因导致：① SUSE12 实际存在且可以执行 lspci 命令② 通过执行 which lspci 命令发现其位于 /sbin/ 目录中③ SUSE12 系统中 /usr/sbin/ 目录和 /sbin/ 目录并不是软链接关系④ x2openEuler 工具收集硬件信息时执行的 lspci 命令是带绝对路径的 /usr/sbin/lspci 最终导致硬件信息收集失败，检查中断三、解决方案此问题并非必现，具体出现原因可能与用户环境配置相关。若遇到此问题可以创建一个软连接 /usr/sbin/lspci 到 /sbin/lspci 最终还是建议工具能够注意并修复一下这个问题，避免不必要的麻烦
本文基于 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
使用 x2openEuler 升级过程遇到 can not clean repo info before upgrade 报错的解决方案
1 问题背景近期又遇到多起在升级过程中报错，报错信息为 “can not clean repo info before upgrade”，如下图所示：这是因为在待升级节点执行 dnf clean all 命令时报错此时很多朋友会有疑问：我的操作系统没有装 dnf ，我的操作系统上不能装 dnf ，等等，那么为什么要去执行 dnf clean all 命令呢？这要从工具升级的原理说起，在报错信息的上面几行有这样的信息：...... [ INFO ] - [initramfs]: start upgrade your system by dnf [ INFO ] - [initramfs]: start construct dnf [ INFO ] - [initramfs]: replace yum to dnf. [ INFO ] - [initramfs]: start to delete yum [ INFO ] - [initramfs]: construct dnf in your system success [ INFO ] - [initramfs]: your system will use dnf to upgrade. ......明显可以看到，工具做了一系列操作：开始构建 dnf使用 dnf 去替换 yum开始删除 yum成功在你的操作系统上构建 dnf你的系统将使用 dnf 去升级dnf 是 yum 的下一代版本，dnf 比 yum更快速和高效，并且 dnf 在解决软件包依赖关系方面比 yum 更强大和智能，能够更好地处理复杂的依赖关系，这也是为什么工具或者以后的操作系统都是用 dnf 作为包管理工具的原因既然知道了症结所在，那么就可以对症下药了！2 规避方案2.1 执行 dnf clean all 命令查看报错在待升级节点手动执行 dnf clean all 命令查看具体报错：报错显示是和 openssl 的库文件有关，具体信息为：“这个错误表明你的系统中的 libldap 库试图使用 EVP_md2 这个加密库函数，但是这个函数在当前系统中的 OpenSSL 版本中不存在或未定义。 EVP_md2 是一个散列函数，用于计算 MD2 散列值，但在较新版本的OpenSSL 中，可能已经将 MD2 作为过时的算法移除了。”2.2 查看 openssl 版本首先执行 rpm -qa | grep openssl 命令查看系统安装的 openssl 版本：系统安装的 openssl 版本为 1.0.2k其次执行 openssl version -a 查看系统当前在用的 openssl 版本：系统在用的 openssl 版本为 1.1.1w系统安装的 openssl 版本和在用的版本不同，那么高版本的 openssl 必然是编译安装的，在编译安装 openssl 时，又必须需要指定高版本 openssl 库文件的位置，否则不能正常使用2.3 查看指定库的位置在 Centos 操作系统中，共有三种指定库文件位置的方式：将库文件所在目录添加到 /etc/ld.so.conf 文件中将库文件所在目录添加到指定文件，并将此文件放在 /etc/ld.so.conf.d/ 目录中将库文件所在目录添加到 LD_LIBRARY_PATH 环境便变量中（1）针对前两种指定库文件的方式，可以使用以下方法排查：① 确定编译安装的 openssl 库文件所在的目录：② 查找该目录具体写到哪个地方了：③ 从查找到的文件中注释掉该目录，之后执行 ldconfig 刷新动态链接库④ 执行 dnf clean all 命令，若无报错则可以到前端点击“重试”按钮继续升级（2）针对最后一种指定库文件的方式，可以使用以下方法排查：① 确定编译安装的 openssl 库文件所在的目录：② 查看 LD_LIBRARY_PATH 变量是否有定义此目录③ 若有则从该变量中剔除该目录④ 执行 dnf clean all 命令，若无报错则可以到前端点击“重试”按钮继续升级
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）退出救援模式，进入系统，验证缩容结果及系统有无异常至此，根分区成功缩容！
使用 x2openEuler 工具升级后 PAM 模块丢失导致登录失败的解决方案
1 问题背景时间：2023 年 12 月 11 日需求：使用 x2openEuler 工具完成从 CentOS 7.6 到 openEuler 22.03 LTS SP1 的升级后，在终端界面登陆时出现登录失败的报错，但可以使用 SSH 远程登录系统，如下图所示2 问题分析及复现2.1 问题分析在排除了密码输入错误等因素后，使用 SSH 远程登录系统，查看 /var/log/secure 日志，内容如下从日志可以看出，在登录系统时，要进行 PAM 认证，但是找不到认证需要的 pam_tally2.so 库文件，导致认证失败而拒绝登录执行 grep -r pam_tally2.so /etc/pam.d 命令，查看哪个配置文件在调用这个库文件从查询结果可以看到，/etc/pam.d/system-auth 这个配置文件调用此库文件然而在全新安装的 openEuler 22.03 LTS SP1 操作系统中，查看这个配置文件发现调用的是 pam_faillock.so 这个库文件查阅资料后得知，新的 pam 认证软件包弃用了 pam_tally2 模块，而是采用 pam_faillock 模块，那么出现了一个问题：在升级到 openEuler 22.03 LTS SP1 操作系统后，对应的 pam 软件包也被升级了，但是怎么还使用了旧版本的模块呢？查看 /etc/pam.d 目录下的所有文件，出现了名为 system-suth.rpmsave 的文件，查看此文件的内容，发现在升级前配置过连续登录失败锁定用户的安全加固项，在升级系统生成新配置文件时，引用了错误的库文件为什么会出现 *.rpmsave 文件呢？这是由构建 RPM 包时的 SEPC 文件决定的。若使用了 %config 关键字标记了配置文件，表示在升级 rpm 包时，若旧配置文件没有被修改过，那么使用新配置文件覆盖旧配置文件，旧配置文件被删除；若旧配置文件被修改过，那么仍然使用新配置文件覆盖旧配置文件，但旧配置文件会以 *.rpmsave 的形式保留下来2.2 问题复现2.2.1 准备工作准备如下表所示的机器 版本号用途源操作系统CentOS 7.6配置安全加固项后升级目标操作系统openEuler 22.03 LTS SP1使用终端登录验证2.2.2 源操作系统配置（1）配置连续登录失败锁定账户的安全加固项# 配置连续登录失败锁定账户的安全加固项 $ sed -i '/#%PAM-1.0/a auth \t required \t pam_tally2.so deny=3 lock_time=30 even_deny_root root_unlock_time=30 per_user reset' /etc/pam.d/system-auth 参数说明： pam_tally2.so 使用 pam_tally2.so 模块，不同 pam 版本调用的模块可能不同 deny=3 用户连续输入错误密码的次数 lock_time=300 普通用户连续输入错误密码后锁定时间，单位：秒 even_deny_root 对 root 用户生效 root_unlock_time=30 root 用户连续输入错误密码后锁定时间，单位：秒 per_user reset 解锁时间到了以后，清除用户锁定状态重启操作系统，连续三次输入错误密码，查看配置是否生效# 查看 root 用户登录失败记录 $ pam_tally2 --user root Login Failures Latest failure From root 2 12/27/23 10:30:30 tty1（2）使用 x2openEuler 工具升级到目标操作系统2.2.3 目标操作系统验证在 tty 终端登录系统报错使用 SSH 远程登录后，查看 /var/log/secure 日志# 查看 /var/log/secure 日志 $ vim /var/log/secure ...... Dec 27 11:23:37 localhost login[5251]: PAM unable to dlopen(/usr/lib64/security/pam_tally2.so): /usr/lib64/security/pam_tally2.so: cannot open shared object file: No such file or directory Dec 27 11:23:37 localhost login[5251]: PAM adding faulty module: /usr/lib64/security/pam_tally2.so Dec 27 11:23:41 localhost login[5251]: pam_succeed_if(login:auth): requirement "uid >= 1000" not met by user "root" Dec 27 11:23:43 localhost login[5251]: FAILED LOGIN SESSION FROM tty1 FOR root, Module is unknown报错内容与生产环境一致，成功复现了问题3 解决措施3.1 如何临时补救共有两种临时补救方案，详见下文3.1.1 补全缺失的库文件补救思路：根据报错内容，从备份目录 /.osbak 中找到缺失的库文件，然后将库文件复制到当前操作系统的对应目录存在问题：因为新版本不再使用这个库文件，人为复制过来调用，会造成额外的资源消耗，并且在以后升级该软件包时也会遇到一些问题，治标不治本操作流程：# 查看 /var/log/secure 日志 $ vim /var/log/secure ...... Dec 27 11:23:37 localhost login[5251]: PAM unable to dlopen(/usr/lib64/security/pam_tally2.so): /usr/lib64/security/pam_tally2.so: cannot open shared object file: No such file or directory Dec 27 11:23:37 localhost login[5251]: PAM adding faulty module: /usr/lib64/security/pam_tally2.so Dec 27 11:23:41 localhost login[5251]: pam_succeed_if(login:auth): requirement "uid >= 1000" not met by user "root" Dec 27 11:23:43 localhost login[5251]: FAILED LOGIN SESSION FROM tty1 FOR root, Module is unknown # 查找缺失的库文件 $ find / -name pam_tally2.so /.osbak/usr/lib64/security/pam_tally2.so # 复制查找到的库文件到 /usr/lib64/security 目录 $ cp /.osbak/usr/lib64/security/pam_tally2.so /usr/lib64/security/能够成功在 tty 终端登录系统3.1.2 修改配置文件补救思路：根据报错内容，查找是哪个配置文件调用了缺失的库文件，然后注释掉配置文件中调用缺失模块的代码存在问题：相比 3.3.1 中的解决办法，不会造成额外资源消耗，说得上是比较稳妥的处理办法，但是毕竟和新版本的配置文件不同，可能影响后续的配置操作流程：# 查看 /var/log/secure 日志 $ vim /var/log/secure ...... Dec 27 11:23:37 localhost login[5251]: PAM unable to dlopen(/usr/lib64/security/pam_tally2.so): /usr/lib64/security/pam_tally2.so: cannot open shared object file: No such file or directory Dec 27 11:23:37 localhost login[5251]: PAM adding faulty module: /usr/lib64/security/pam_tally2.so Dec 27 11:23:41 localhost login[5251]: pam_succeed_if(login:auth): requirement "uid >= 1000" not met by user "root" Dec 27 11:23:43 localhost login[5251]: FAILED LOGIN SESSION FROM tty1 FOR root, Module is unknown # 查找缺失的库文件被哪个配置文件调用 $ grep -r pam_tally2.so /etc/pam.d/ /etc/pam.d/system-auth:auth required pam_tally2.so deny=3 lock_time=30 even_deny_root root_unlock_time=30 per_user reset # 注释或删除相应的代码 $ sed -i '/pam_tally2.so/ s/^/#/' /etc/pam.d/system-auth能够成功在 tty 终端登录系统3.2 如何完美解决共有两种临时解决方案，详见下文3.2.2 使用新配置文件覆盖旧文件解决思路：根据报错内容，查找是哪个配置文件调用了缺失的库文件，然后查看该配置文件的同级目录下，是否有与该配置文件同名但是后缀为 .rpmnew 的文件，使用 *.rpmnew 文件覆盖旧文件方案特点：这是软件包升级后根据旧配置文件生成的新配置文件，可以大胆正常使用，但前提是生成了 *.rpmnew 配置文件操作流程：# 查看 /var/log/secure 日志 $ vim /var/log/secure ...... Dec 27 11:23:37 localhost login[5251]: PAM unable to dlopen(/usr/lib64/security/pam_tally2.so): /usr/lib64/security/pam_tally2.so: cannot open shared object file: No such file or directory Dec 27 11:23:37 localhost login[5251]: PAM adding faulty module: /usr/lib64/security/pam_tally2.so Dec 27 11:23:41 localhost login[5251]: pam_succeed_if(login:auth): requirement "uid >= 1000" not met by user "root" Dec 27 11:23:43 localhost login[5251]: FAILED LOGIN SESSION FROM tty1 FOR root, Module is unknown # 查找缺失的库文件被哪个配置文件调用 $ grep -r pam_tally2.so /etc/pam.d/ /etc/pam.d/system-auth:auth required pam_tally2.so deny=3 lock_time=30 even_deny_root root_unlock_time=30 per_user reset # 查看 /etc/pam.d 目录下的所有相关文件 $ cd /etc/pam.d $ ls -l | grep system-auth -rw-r--r-- 1 root root 1133 12月 27 14:29 system-auth -rw-r--r--. 1 root root 1031 11月 21 21:10 system-auth-ac -rw-r--r-- 1 root root 1496 3月 22 2023 system-auth.rpmnew # 备份旧配置文件 $ mv system-auth system-auth.bak # 恢复新配置文件 $ cp system-auth.rpmnew system-auth能够成功在 tty 终端登录系统3.2.1 从 rpm 包中恢复配置文件解决思路：先查找缺失的库文件被哪个配置文件调用，然后查找这个配置文件来源于哪个软件包，从软件包中恢复该配置文件方案特点：从 rpm 包中恢复出全新的配置文件，替换旧文件，缺点是需要重新配置安全加固项操作流程：（1）安装基础工具# 安装 yumdownloader 包下载工具 $ yum install -y dnf-plugins-core # 安装 cpio 备份工具 $ yum install -y cpio（2）恢复配置文件# 查看 /var/log/secure 日志 $ vim /var/log/secure ...... Dec 27 11:23:37 localhost login[5251]: PAM unable to dlopen(/usr/lib64/security/pam_tally2.so): /usr/lib64/security/pam_tally2.so: cannot open shared object file: No such file or directory Dec 27 11:23:37 localhost login[5251]: PAM adding faulty module: /usr/lib64/security/pam_tally2.so Dec 27 11:23:41 localhost login[5251]: pam_succeed_if(login:auth): requirement "uid >= 1000" not met by user "root" Dec 27 11:23:43 localhost login[5251]: FAILED LOGIN SESSION FROM tty1 FOR root, Module is unknown # 查找缺失的库文件被哪个配置文件调用 $ grep -r pam_tally2.so /etc/pam.d/ /etc/pam.d/system-auth:auth required pam_tally2.so deny=3 lock_time=30 even_deny_root root_unlock_time=30 per_user reset # 查找配置文件来源于哪个 rpm 包 $ rpm -qf /etc/pam.d/system-auth pam-1.5.2-6.oe2203sp1.x86_64 -------------------------------以下内容在 /root 目录操作------------------------------- $ cd /root # 下载查找到的 rpm 包 $ yumdownloader pam-1.5.2-6.oe2203sp1.x86_64 # 查看下载的 rpm 包 $ ls -l pam-1.5.2-6.oe2203sp1.x86_64.rpm -rw-r--r-- 1 root root 448921 12月 27 14:49 pam-1.5.2-6.oe2203sp1.x86_64.rpm # 执行以下命令恢复配置文件 $ rpm2cpio pam-1.5.2-6.oe2203sp1.x86_64.rpm | cpio -idv ./etc/pam.d/system-auth ./etc/pam.d/system-auth 4127 块 # 在当前目录下会生成恢复的配置文件 $ ls -l ./etc/pam.d/ 总用量 4 -rw-r--r-- 1 root root 1496 12月 27 14:54 system-auth # 备份旧配置文件 $ mv /etc/pam.d/system-auth /etc/pam.d/system-auth.bak # 恢复新配置文件 $ cp etc/pam.d/system-auth /etc/pam.d/能够成功在 tty 终端登录系统