livecd를 부팅하지 않고 루트 파일 시스템을 축소하는 방법


93

이전에 루트 파일 시스템 아래에있는 데이터를 전용 마운트 지점으로 이동하기 위해 시스템 파티션을 다시 정렬해야한다는 것을 알게되었습니다. 볼륨은 모두 LVM에 있으므로 비교적 간단합니다. 새 볼륨을 생성하고, 해당 볼륨으로 데이터를 이동하고, 루트 파일 시스템을 축소 한 다음, 적절한 지점에 새 볼륨을 마운트하십시오.

문제는 루트 파일 시스템을 축소하는 3 단계입니다. 관련된 파일 시스템은 ext4이므로 온라인 크기 조정이 지원됩니다. 그러나 마운트되는 동안 파일 시스템은 확장 될 수만 있습니다. 파티션을 축소하려면 마운트를 해제해야합니다. 물론 정상적인 작업에서는 루트 파티션을 사용할 수 없습니다.

웹 관련 답변은 LiveCD 또는 기타 복구 미디어 부팅, 축소 작업 수행 후 설치된 시스템으로 다시 부팅하는 것 같습니다. 그러나 문제의 시스템은 원격이며 SSH를 통해서만 액세스 할 수 있습니다. 재부팅 할 수 있지만 복구 디스크를 부팅하고 콘솔에서 작업을 수행 할 수 없습니다.

원격 셸 액세스를 유지하면서 루트 파일 시스템을 마운트 해제하려면 어떻게해야합니까?


다른 서버에 루트 파일 시스템을 임시로 마운트 할 수 있습니까? 예를 들어 다른 VM을 가동시키고이 디스크 볼륨을 제공합니까?
스티브

서버는 물리적이므로 아닙니다.
톰 헌트

4
루트를 tmpfs로 복사하십시오 pivot_root. 여기의 예는 dreamlayers.blogspot.co.uk/2012/10/running-linux-from-ram.html- 까다 롭지 만 시험해 볼 테스트 상자가 있다면 고려할 가치가 있습니다.
스티브

1
ssh를 통한 원격 액세스가 ivarch.com/blogs/oss/2007/01/…
steve

2
루트 LVM이 충분히 작 으면 다른 LVM에 복제하여 grub에서 부트 식당 (임시 새로운 기본값)을 생성 한 다음 부팅하여 "라이브 시스템"으로 만들 수 있습니다.
Rabin

답변:


169

이 문제를 해결하면서 http://www.ivarch.com/blogs/oss/2007/01/resize-a-live-root-fs-a-howto.shtml 에 제공된 정보 는 매우 중요했습니다. 그러나이 가이드는 매우 오래된 버전의 RHEL 용이며 다양한 정보가 더 이상 사용되지 않습니다.

아래 지침은 CentOS 7에서 작동하도록 제작되었지만 systemd를 실행하는 배포판으로 쉽게 전환 할 수 있어야합니다. 모든 명령은 루트로 실행됩니다.

  1. 시스템이 안정적인 상태인지 확인하십시오

    다른 사람이 사용하지 않고 다른 중요한 일이 일어나지 않도록하십시오. httpd 또는 ftpd와 같은 서비스 제공 장치를 중지하고 외부 연결이 중간에 문제를 일으키지 않도록하는 것이 좋습니다.

    systemctl stop httpd
    systemctl stop nfs-server
    # and so on....
    
  2. 사용하지 않는 모든 파일 시스템 마운트 해제

    umount -a
    

    루트 볼륨 자체와 다양한 임시 / 시스템 FS에 대해 여러 개의 'Target is busy'경고가 표시됩니다. 현재로서는 무시할 수 있습니다. 중요한 것은 루트 파일 시스템 자체를 제외하고는 온 디스크 파일 시스템이 마운트 된 상태로 남아 있지 않다는 것입니다. 이것을 확인하십시오 :

    # 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. 임시 뿌리 폐기

    /tmp/tmproot대신 사용하지 않고 5 단계와 6 단계를 반복하십시오 /oldroot. 그때:

    umount /tmp/tmproot
    rmdir /tmp/tmproot
    

    그것이 tmpfs이므로,이 시점에서 임시 루트는 에테르로 녹아 다시는 볼 수 없습니다.

  10. 물건을 제자리에 돌려 놓으십시오

    파일 시스템을 다시 마운트하십시오.

    mount -a
    

    이 시점에서, 당신은 또한 업데이트해야 /etc/fstab하고 grub.cfg어떤 조정에 따라 당신은 7 단계 동안했다.

    실패한 서비스를 다시 시작하십시오.

    systemctl | grep failed
    systemctl restart <whatever>
    

    공유 서브 트리를 다시 허용하십시오.

    mount --make-rshared /
    

    중지 된 서비스 단위를 시작하십시오.이 단일 명령을 사용할 수 있습니다.

    systemctl isolate default.target
    

그리고 당신은 끝났습니다.

RHEL4에서이 진화를 수행 한 Andrew Wood와 저에게 이전과의 링크를 제공 한 Steve에게 감사드립니다.


11
멋진 답변입니다. 거의 마법적이고 매우 명확하고 간단합니다. 아무런 문제없이 데비안 VPS와 함께 사용했습니다 ( umount /oldroot/boot물론 6 단계). 귀하의 답변을 답변이 없거나 부정적인 답변이없는 다른 SE 질문에 연결하고 있습니다.
vaab '

3
그리고 문제는 @vaab이 지적한 바와 같습니다. 당신은 당신 umount /oldroot/boot앞에umount /oldroot
ToBeReplaced

3
요점은 물리적 콘솔없이 루트 파일 시스템을 마운트 해제하고 조작하는 것입니다. 내가 아는 한, 파티션을 마운트 해제하는 동안 파티션에서 읽는 서비스를 열어 둘 수는 없습니다. 서비스가 루트 FS에 닿지 않으면 mount --movetmpfs를 사용하여 열어 둘 수 는 있지만 지원되지 않습니다.
Tom Hunt

2
init 데몬을 재시작하려면 OS 기능을 사용해야합니다. 나는 upstart를 사용한 적이 없지만 wiki.ubuntu.com/FoundationsTeam/Specs/…telinit u그것이 당신이 원하는 것을 할 수 있다고 제안합니다 .
Tom Hunt

3
내가 추가로 겪은 주름 : / tmp는 시스템의 램 디스크이므로에 마운트 된 램 디스크 /oldroot/tmp로 인해 마운트를 해제 /oldroot하지 못했지만 표시 fuser되거나 lsof출력 되지 않습니다 . 그 중 하나를 해결하기 위해 systemd를 쳐다 보는 것을 조금 보았습니다 ...
Chris Kitching

7

실험하고 있지 않은 일을 확신한다면 비대화 식이며 빠른 방법 인 initrd에 연결할 수 있습니다.

데비안 기반 시스템에서 방법은 다음과 같습니다.

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


답을 할 때 왜 답되는지에 대해 설명 하는 것이 좋습니다 .
Stephen Rauch

1
이것은 건전한 접근법입니다. 필요한 조작을 대화식으로 수행 할 수있게 된 것이 좋습니다. 그러나 이것은 아마도 더 빠를 것입니다. 답변 자체에 대한 자세한 내용을 편집하거나 다른 플랫폼을 고려하는 것이 좋습니다 (이 일반적인 접근법은 여전히 ​​dracut 또는 mkinitcpio 또는 다른 모호한 최신 initramfs 생성기와 함께 작동하는 것 같습니다).
Tom Hunt

미안 @ stephen-rauch 나는 단지 실행이 아닌 아이디어를 지적하고있었습니다.
Szépe Viktor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.