确保系统处于稳定状态
确保没有人在使用它,并且没有其他重要的事情在进行。最好停止服务提供单元(例如httpd或ftpd),以确保外部连接不会干扰中间的事物。
systemctl stop httpd
systemctl stop nfs-server
# and so on....
卸载所有未使用的文件系统
umount -a
这将为根卷本身以及各种临时/系统FS打印许多“目标正忙”警告。这些可以暂时忽略。重要的是,除了根文件系统本身之外,没有其他磁盘文件系统保持挂载状态。验证一下:
# mount alone provides the info, but column makes it possible to read
mount | column -t
如果看到任何磁盘文件系统仍在挂载,则表明某些东西仍在运行,而这本不应该这样。检查它在使用什么fuser
:
# if necessary:
yum install psmisc
# then:
fuser -vm <mountpoint>
systemctl stop <whatever>
umount -a
# repeat as required...
设为临时根
mkdir /tmp/tmproot
mount -t tmpfs none /tmp/tmproot
mkdir /tmp/tmproot/{proc,sys,dev,run,usr,var,tmp,oldroot}
cp -ax /{bin,etc,mnt,sbin,lib,lib64} /tmp/tmproot/
cp -ax /usr/{bin,sbin,lib,lib64} /tmp/tmproot/usr/
cp -ax /var/{account,empty,lib,local,lock,nis,opt,preserve,run,spool,tmp,yp} /tmp/tmproot/var/
这将创建一个非常小的根系统,这会破坏(除其他外)联机帮助页查看(否/usr/share
),用户级别的自定义项(否/root
或/home
)等。这是故意的,因为这鼓励不要在必要的陪审团中扎根。
此时,您还应确保已安装所有必需的软件,因为这也肯定会破坏软件包管理器。浏览所有步骤,并确保您具有必要的可执行文件。
透视成根
mount --make-rprivate / # necessary for pivot_root to work
pivot_root /tmp/tmproot /tmp/tmproot/oldroot
for i in dev proc sys run; do mount --move /oldroot/$i /$i; done
systemd导致挂载默认情况下允许子树共享(与一样mount --make-shared
),这会导致pivot_root
失败。因此,我们使用全局关闭了此功能mount --make-rprivate /
。系统和临时文件系统被批量移动到新的根目录中。这是使其完全工作所必需的;与systemd通信的套接字位于其中/run
,因此无法使正在运行的进程关闭它。
确保远程访问在转换后仍然存在
systemctl restart sshd
systemctl status sshd
重新启动sshd之后,通过打开另一个终端并通过ssh重新连接到机器来确保您可以进入。如果无法解决问题,请继续解决问题。
验证之后,您可以再次连接,退出当前使用的外壳并重新连接。这样可以使剩下的叉子sshd
退出,并确保新的叉子不被抓住/oldroot
。
使用旧根关闭所有内容
fuser -vm /oldroot
这将打印仍保留在旧根目录下的进程列表。在我的系统上,它看起来像这样:
USER PID ACCESS COMMAND
/oldroot: root kernel mount /oldroot
root 1 ...e. systemd
root 549 ...e. systemd-journal
root 563 ...e. lvmetad
root 581 f..e. systemd-udevd
root 700 F..e. auditd
root 723 ...e. NetworkManager
root 727 ...e. irqbalance
root 730 F..e. tuned
root 736 ...e. smartd
root 737 F..e. rsyslogd
root 741 ...e. abrtd
chrony 742 ...e. chronyd
root 743 ...e. abrt-watch-log
libstoragemgmt 745 ...e. lsmd
root 746 ...e. systemd-logind
dbus 747 ...e. dbus-daemon
root 753 ..ce. atd
root 754 ...e. crond
root 770 ...e. agetty
polkitd 782 ...e. polkitd
root 1682 F.ce. master
postfix 1714 ..ce. qmgr
postfix 12658 ..ce. pickup
您需要先处理这些过程中的每一个,然后才能卸载/oldroot
。暴力方法仅kill $PID
适用于每个人,但这可能会破坏事情。要更轻柔地做它:
systemctl | grep running
这将创建正在运行的服务的列表。您应该能够将此与持有的进程列表相关联/oldroot
,然后systemctl restart
为每个进程进行发布。某些服务将拒绝在临时根目录中启动并进入失败状态;这些暂时并不重要。
如果要调整大小的根驱动器是LVM驱动器,则即使它们未显示在所创建的列表中,您也可能需要重新启动一些其他正在运行的服务fuser -vm /oldroot
。如果发现在步骤7下无法调整LVM驱动器的大小,请尝试systemctl restart systemd-udevd
。
有些过程无法通过simple处理systemctl restart
。对我而言,其中包括auditd
(不希望通过杀死systemctl
,因此只想要一个kill -15
)。这些可以单独处理。
通常,您会找到的最后一个过程是systemd
它本身。为此,请运行systemctl daemon-reexec
。
完成后,该表应如下所示:
USER PID ACCESS COMMAND
/oldroot: root kernel mount /oldroot
卸载旧根
umount /oldroot
此时,您可以执行所需的任何操作。最初的问题需要一个简单的resize2fs
调用,但是您可以在这里做任何您想做的事。另一种用例是将根文件系统从简单分区转移到LVM / RAID /其他。
向后旋转根
mount <blockdev> /oldroot
mount --make-rprivate / # again
pivot_root /oldroot /oldroot/tmp/tmproot
for i in dev proc sys run; do mount --move /tmp/tmproot/$i /$i; done
这是第4步的直接逆转。
处置临时根
重复步骤5和6,但要使用/tmp/tmproot
代替/oldroot
。然后:
umount /tmp/tmproot
rmdir /tmp/tmproot
由于它是tmpfs,因此此时临时根溶解到以太中,再也看不到了。
把东西放回原处
再次挂载文件系统:
mount -a
此时,您还应该更新/etc/fstab
并grub.cfg
根据在步骤7中所做的任何调整。
重新启动所有失败的服务:
systemctl | grep failed
systemctl restart <whatever>
再次允许共享子树:
mount --make-rshared /
启动已停止的服务单元-您可以使用以下单个命令:
systemctl isolate default.target