如何在不启动livecd的情况下缩小根文件系统


93

我发现自己需要重新布置系统的分区,以将先前在根文件系统下的数据移至专用的挂载点。卷都在LVM中,因此这相对容易:创建新卷,将数据移入其中,收缩根文件系统,然后在适当的位置挂载新卷。

问题是步骤3,缩小根文件系统。涉及的文件系统是ext4,因此支持在线调整大小。但是,在挂载时,只能增长文件系统。要缩小分区,需要先将其卸装,这对于正常运行中的根分区当然是不可能的。

围绕Web的答案似乎与引导LiveCD或其他应急媒体,执行收缩操作,然后重新引导至已安装的系统有关。但是,有问题的系统是远程的,我只能通过SSH访问。我可以重新启动,但是无法从控制台启动应急光盘和操作。

如何在维护远程Shell访问的同时卸载根文件系统?


是否有机会将根文件系统临时挂载到其他服务器上?例如启动另一个VM并向其提供此磁盘卷?
史蒂夫(Steve)2015年

服务器是物理的,所以没有。
汤姆·亨特

4
将root复制到tmpfs并pivot_root在那里。这里有一个示例dreamlayers.blogspot.co.uk/2012/10/running-linux-from-ram.html-有点棘手,但是如果您有测试盒可以尝试,值得考虑。
史蒂夫(Steve)2015年

1
这里的另一个例子是通过ssh进行的远程访问被认为是ivarch.com/blogs/oss/2007/01/…–
Steve

2
如果根LVM足够小,则可以将其克隆到另一个LVM,并在grub中创建引导餐厅(临时默认的新临时目录)以使用它,然后从其引导(使其成为您的“实时系统”)
Rabin

Answers:


169

为解决此问题,http: //www.ivarch.com/blogs/oss/2007/01/resize-a-live-root-fs-a-howto.shtml 提供的信息至关重要。但是,该指南适用于RHEL的非常旧的版本,并且各种信息已过时。

下面的说明旨在与CentOS 7一起使用,但是它们应该足够容易地转移到运行systemd的任何发行版中。所有命令都以root用户身份运行。

  1. 确保系统处于稳定状态

    确保没有人在使用它,并且没有其他重要的事情在进行。最好停止服务提供单元(例如httpd或ftpd),以确保外部连接不会干扰中间的事物。

    systemctl stop httpd
    systemctl stop nfs-server
    # and so on....
    
  2. 卸载所有未使用的文件系统

    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...
    
  3. 设为临时根

    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)等。这是故意的,因为这鼓励不要在必要的陪审团中扎根。

    此时,您还应确保已安装所有必需的软件,因为这也肯定会破坏软件包管理器。浏览所有步骤,并确保您具有必要的可执行文件。

  4. 透视成根

    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,因此无法使正在运行的进程关闭它。

  5. 确保远程访问在转换后仍然存在

    systemctl restart sshd
    systemctl status sshd
    

    重新启动sshd之后,通过打开另一个终端并通过ssh重新连接到机器来确保您可以进入。如果无法解决问题,请继续解决问题。

    验证之后,您可以再次连接,退出当前使用的外壳并重新连接。这样可以使剩下的叉子sshd退出,并确保新的叉子不被抓住/oldroot

  6. 使用旧根关闭所有内容

    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
    
  7. 卸载旧根

    umount /oldroot
    

    此时,您可以执行所需的任何操作。最初的问题需要一个简单的resize2fs调用,但是您可以在这里做任何您想做的事。另一种用例是将根文件系统从简单分区转移到LVM / RAID /其他。

  8. 向后旋转根

    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步的直接逆转。

  9. 处置临时根

    重复步骤5和6,但要使用/tmp/tmproot代替/oldroot。然后:

    umount /tmp/tmproot
    rmdir /tmp/tmproot
    

    由于它是tmpfs,因此此时临时根溶解到以太中,再也看不到了。

  10. 把东西放回原处

    再次挂载文件系统:

    mount -a
    

    此时,您还应该更新/etc/fstabgrub.cfg根据在步骤7中所做的任何调整。

    重新启动所有失败的服务:

    systemctl | grep failed
    systemctl restart <whatever>
    

    再次允许共享子树:

    mount --make-rshared /
    

    启动已停止的服务单元-您可以使用以下单个命令:

    systemctl isolate default.target
    

这样就完成了。

非常感谢Andrew Wood(他在RHEL4上进行了这种改进)和Steve(向我提供了到前者的链接)。


11
很棒的答案。几乎是神奇的,而且非常清晰直接。它与debian VPS一起使用时没有任何问题(umount /oldroot/boot当然,必须在第6阶段进行)。我正在将您的答案与其他没有回应或否定答案的SE问题相关联。
vaab '16

3
解决后,问题就如@vaab所示;您必须umount /oldroot/boot在自己之前umount /oldroot
ToBeReplaced

3
关键是无需物理控制台即可卸载和操作根文件系统。据我所知,没有办法在卸载该分区的同时保持打开从该分区读取的服务。如果您的服务没有触及根FS,则可以使用mount --movetmpfs 使其保持打开状态,但是不支持。
汤姆·亨特

2
您需要使用OS设备来重新启动init守护程序。我从未使用过新贵,但是wiki.ubuntu.com/FoundationsTeam/Specs/…建议这样telinit u做可能会满足您的要求。
汤姆·亨特

3
另外一个皱纹我跑进:/ tmp目录是我的系统上一个ramdisk,所以我结束了安装在一个ramdisk /oldroot/tmp,这让我无法卸载/oldroot,但不显示fuserlsof输出。有点盯着systemd来解决那个问题……
克里斯·基奇

7

如果您确定自己在做什么-可以不做实验,则可以使用initrd,它是一种非交互式且快速的方法。

在基于Debian的系统上,方法如下。

参见代码:https : //github.com/szepeviktor/debian-server-tools/blob/master/debian-resizefs.sh

还有另一个例子:https : //github.com/szepeviktor/debian-server-tools/blob/master/debian-convert-ext3-ext4.sh


给出答案时,最好对原因做出一些解释
斯蒂芬·劳赫

1
这是一个合理的方法。我喜欢我让我互动地进行必要的操作;但是,这可能更快。将更多详细信息编辑到答案本身中,或者考虑使用其他平台,这可能是个好主意(似乎这种通用方法仍然适用于dracut或mkinitcpio或任何其他模糊的initramfs生成器)。
汤姆·亨特

抱歉@ stephen-rauch我只是指出这个想法而不是执行。
Szépe维克托·
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.