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

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

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

如何在保持远程外壳程序访问的同时卸载根文件系统?

评论

是否有机会将根文件系统临时挂载到其他服务器上?例如旋转另一个VM并向其显示此磁盘卷?

服务器是物理服务器,所以没有。

将root复制到tmpfs,然后将pivot_root复制到那里。这里的一个例子dreamlayers.blogspot.co.uk/2012/10/running-linux-from-ram.html-有点棘手,但是如果您有一个测试箱可以尝试,值得考虑。

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

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

#1 楼

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

以下说明是为与CentOS 7一起使用而设计的,但是它们应该可以很容易地转移到运行的任何发行版中。系统化的。所有命令均以root用户身份运行。



确保系统处于稳定状态

确保没有其他人在使用它,并且没有其他东西重要的是继续。停止httpd或ftpd之类的服务提供单元可能是一个好主意,只是为了确保外部连接不会破坏中间的事物。

systemctl stop httpd
systemctl stop nfs-server
# and so on....



>卸载所有未使用的文件系统

umount -a


这将为根卷本身以及各种临时/系统FS打印许多“目标正忙”警告。这些可以暂时忽略。重要的是,除了根文件系统本身之外,没有其他磁盘文件系统保持挂载状态。验证以下内容:如果您看到仍在挂载任何磁盘文件系统,则表明仍在运行某些不该运行的文件系统。使用fuser检查它是什么:

# mount alone provides the info, but column makes it possible to read
mount | column -t



创建临时根

# if necessary:
yum install psmisc
# then:
fuser -vm <mountpoint>
systemctl stop <whatever>
umount -a
# repeat as required...


这里创建一个非常小的根系统,这会中断(尤其是)联机帮助页查看(否/usr/share),用户级自定义项(否/root/home)等等。这是有意的,因为这鼓励不要在评审团操纵的根系统中停留任何时间。

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


转到根目录

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/


systemd导致挂载默认情况下允许子树共享(与mount --make-shared一样),这会导致pivot_root失败。因此,我们使用mount --make-rprivate /在全球范围内将其关闭。系统和临时文件系统被批量移动到新的根目录中。这是使其完全工作所必需的;与systemd通信的套接字位于/run中,因此无法关闭正在运行的进程。


确保远程访问在转换后不受影响

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


重新启动sshd之后,请确保可以进入,方法是打开另一个终端,然后再次通过ssh连接到计算机。如果不能,请在继续操作之前解决问题。

一旦确认可以再次连接,请退出当前使用的Shell并重新连接。这将允许其余的分叉sshd退出,并确保新的/oldroot不持有/oldroot


仍使用旧根关闭所有内容

systemctl restart sshd
systemctl status sshd


这将打印仍保留在旧根目录中的进程列表。在我的系统上,它看起来像这样:

fuser -vm /oldroot


您需要先处理以下每个过程,然后才能卸载kill $PID。暴力破解方法只是简单地使用/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


这将创建正在运行的服务的列表。您应该能够将其与持有systemctl restart的进程列表相关联,然后为每个进程发出fuser -vm /oldroot。某些服务将拒绝在临时根目录中启动并进入失败状态;这些现在暂时并不重要。

如果要调整大小的根驱动器是LVM驱动器,则即使它们未显示在其中,您也可能需要重新启动一些其他正在运行的服务。由systemctl restart systemd-udevd创建的列表。如果发现无法在步骤7下调整LVM驱动器的大小,请尝试systemctl restart

有些过程无法通过简单的auditd处理。对我来说,其中包括systemctl(不希望通过kill -15杀死它,所以只想要一个systemd)。这些可以单独处理。

您通常会找到的最后一个过程是systemctl daemon-reexec本身。为此,请运行resize2fs。完成后,表应如下所示:

systemctl | grep running



旧根

             USER        PID ACCESS COMMAND
/oldroot:    root     kernel mount /oldroot


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


将根向后旋转

umount /oldroot


这是对步骤4的直接逆转。


处理临时根

重复步骤5和6,但使用/oldroot代替/etc/fstab 。然后:

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


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


将内容放回原处

再次安装文件系统:

umount /tmp/tmproot
rmdir /tmp/tmproot


此时,您还应该在以下位置更新grub.cfg和q4312079q根据您在步骤7中所做的任何调整。

重新启动任何失败的服务:

mount -a


再次允许共享子树:

systemctl | grep failed
systemctl restart <whatever>


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

mount --make-rshared /



完成。

非常感谢Andrew Wood(他在RHEL4上完成了这一演进),以及Steve(为我提供了到前者的链接)。

评论


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

–vaab
16年1月1日在2:03

解决后,问题就如@vaab所示;您必须先挂载/ oldroot / boot,然后再挂载/ oldroot

–要替换
16年5月13日在10:10

关键是无需物理控制台即可卸载和操作根文件系统。据我所知,在卸载该分区时无法保持打开从分区读取的服务。如果您的服务没有接触到根FS,则可以使用mount --move将其保持打开状态,进入tmpfs,但这是不受支持的。

–汤姆·亨特(Tom Hunt)
16-10-7在2:01

您需要使用OS设备来重新启动init守护程序。我从未使用过新贵,但是wiki.ubuntu.com/FoundationsTeam/Specs/…建议telinit u可以满足您的要求。

–汤姆·亨特(Tom Hunt)
17年1月31日在16:09

我遇到的另一个问题是:/ tmp是系统上的ramdisk,所以我最终在/ oldroot / tmp上安装了一个ramdisk,这阻止了我卸载/ oldroot,但没有出现在热熔器或lsof输出中。有点盯着systemd来解决那个问题...

–克里斯·基钦(Chris Kitching)
17年8月27日在3:48



#2 楼

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

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

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

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

评论


给出答案时,最好对原因做出一些解释。

–斯蒂芬·劳赫(Stephen Rauch)
17年2月15日在15:33

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

–汤姆·亨特(Tom Hunt)
17年2月15日在17:39

抱歉@ stephen-rauch我只是指出这个想法而不是执行。

–SzépeViktor
17年2月15日在20:09

感谢您的更新Étienne

–SzépeViktor
20-2-19在15:45

#3 楼

我在DigitalOcean VPS上执行的操作(已将25G / dev / vda1设置为root用户):


使用fdisk删除第一个(25G)分区
创建20G分区(第一个扇区必须与原始扇区相同)
创建一个新分区(显然大小为5G),它将是/ dev / vda2
写入分区表并退出fdisk。
创建一个/ dev / vda2上的ext4文件系统
请注意两个分区的UUID(ls -l / dev / disk / by-uuid)
将/ dev / vda1 UUID替换为/ boot /中的/ dev / vda2 UUID grub / grub.cfg和/ etc / fstab
将/ dev / vda2挂载到/ mnt
从/复制所有内容(dev,proc,run,sys,mnt除外)到/ mnt
运行update-grub


reboot并祈祷

当我被告知不支持resize2fs时,上述方法效果很好。

评论


仅当/ dev / vda1上的所有数据都在设备的前20G之内时,此方法才有效。因此,它要求第一个分区的满容量小于80%,而永远不要超过80%。而且,无法通过用户空间工具验证这种情况,因此当覆盖分区的最后5G时,数据丢失会导致骰子滚动。

–汤姆·亨特(Tom Hunt)
20-4-17的16:40