It is possible, though difficult, to resize a Linux root partition while
it's still mounted. What's more, it can be done remotely, without
having to be at the console. You'll need 2GB of RAM, but here is how:
The above has only been tested on RHEL AS 4, but something like it should work on most Linux variants that have
Update: Lucas Chan says, for CentOS 4.4, "I was not able to login after restarting
Update: Simetrical suggests that 64-bit systems also need to copy
- Stop all services other than the network and SSH, and stop SELinux interfering:
# telinit 2
# for SERVICE in \
`chkconfig --list | grep 2:on | awk '{print $1}' | grep -v -e sshd -e network -e rawdevices`; \
do service $SERVICE stop; done
# service nfs stop
# service rpcidmapd stop
# setenforce 0 - Unmount all filesystems:
# umount -a
- Create a temporary filesystem:
# mkdir /tmp/tmproot
Note that this used up about 1.6GB of ramdisk on my Red Hat Enterprise Linux (AS) 4 server.
# mount none /tmp/tmproot -t tmpfs
# mkdir /tmp/tmproot/{proc,sys,usr,var,oldroot}
# cp -ax /{bin,etc,mnt,sbin,lib} /tmp/tmproot/
# cp -ax /usr/{bin,sbin,lib} /tmp/tmproot/usr/
# cp -ax /var/{account,empty,lib,local,lock,nis,opt,preserve,run,spool,tmp,yp} /tmp/tmproot/var/
# cp -a /dev /tmp/tmproot/dev
Also note that on 64-bit systems you will also need to copy/lib64and/usr/lib64as well, otherwise you will see errors like "lib64/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory". - Switch the filesystem root to the temporary filesystem:
# pivot_root /tmp/tmproot/ /tmp/tmproot/oldroot
# mount none /proc -t proc
# mount none /sys -t sysfs (this may fail on 2.4 systems)
# mount none /dev/pts -t devpts - Restart the SSH daemon to close the old pty devices:
# service sshd restart
You should now try to make a new connection. If that succeeds, close your old one to release the old pty device. If it fails, get the SSH daemon properly restarted before proceeding. - Close everything that's still using the old filesystem:
# umount /oldroot/proc
Now try to find other things that are still holding on to the old filesystem, particularly
# umount /oldroot/dev/pts
# umount /oldroot/selinux
# umount /oldroot/sys
# umount /oldroot/var/lib/nfs/rpc_pipefs/dev:# fuser -vm /oldroot/dev
Common processes that will need killing:# killall udevd
Finally, you will need to re-execute
# killall gconfd-2
# killall mingetty
# killall minilogdinit:# telinit u
- Unmount the old filesystem:
# umount -l /oldroot/dev
Note that we use the
# umount /oldrootumount -l("lazy") option, available only with kernels 2.4.11 and later, because/oldrootis actually mounted using an entry in/oldroot/dev, so it would be difficult if not impossible to unmount either of them otherwise. - Now resize the root filesystem:
# e2fsck -C 0 -f /dev/VolGroup00/LogVol00
In this example the root partition is
# resize2fs -p -f /dev/VolGroup00/LogVol00 8G
# lvresize /dev/VolGroup00/LogVol00 -L 8G
# resize2fs -p -f /dev/VolGroup00/LogVol00
# e2fsck -C 0 -f /dev/VolGroup00/LogVol00/dev/VolGroup00/LogVol00and it is being shrunk to 8GB. You don't necessarily have to runresize2fstwice, I just do in case my idea of the size differs from whatlvresizethinks. - We're done, so start putting everything back:
# mount /dev/VolGroup00/LogVol00 /oldroot
Now make a new SSH connection, and if it works, close the old one. Note that
# pivot_root /oldroot /oldroot/tmp/tmproot
# umount /tmp/tmproot/proc
# mount none /proc -t proc
# cp -ax /tmp/tmproot/dev/* /dev/
# mount /dev/pts
# mount /sys
# killall mingetty
# telinit u
# service sshd restartsshdmay still be running in the temporary filesystem at this point because of the way theservicescripts work - check this withfuser, and if this is the case, kill the oldestsshdprocess and then doservice sshd start. Then log in again and disconnect all other connections.
Final steps to unmount the temporary filesystem:# umount -l /tmp/tmproot/dev/pts
Now to re-mount our original filesystems and start services back up:
# umount -l /tmp/tmproot
# rmdir /tmp/tmproot# mount -a
Replace
# umount /sys
# mount /sys
# for SERVICE in \
`chkconfig --list | grep 2:on | awk '{print $1}' | grep -v -e sshd -e network -e rawdevices`; \
do service $SERVICE start; done
# telinit 33with your preferred runlevel. You may also want to start SELinux up again withsetenforce.
The above has only been tested on RHEL AS 4, but something like it should work on most Linux variants that have
pivot_root, tmpfs, and umount -l, so long as you can replace the chkconfig and service parts with whatever is appropriate for your distribution.Update: Lucas Chan says, for CentOS 4.4, "I was not able to login after restarting
sshd in step 5 until I did this: mount none /dev/pts -t devpts".Update: Simetrical suggests that 64-bit systems also need to copy
/lib64 and /usr/lib64, and that after pivot_root 2.6 kernels will also need mount none /sys -t sysfs and mount none /dev/pts -t devpts. (The above steps have been modified accordingly).