Làm thế nào để thu nhỏ hệ thống tập tin gốc mà không cần khởi động một livecd


93

Tôi thấy mình cần sắp xếp lại các phân vùng của một hệ thống để di chuyển dữ liệu trước đó dưới hệ thống tập tin gốc vào các điểm gắn kết chuyên dụng. Các ổ đĩa đều có trong LVM, vì vậy điều này tương đối dễ dàng: tạo các ổ đĩa mới, di chuyển dữ liệu vào chúng, thu nhỏ hệ thống tập tin gốc, sau đó gắn kết các ổ đĩa mới tại các điểm thích hợp.

Vấn đề là bước 3, thu hẹp hệ thống tập tin gốc. Các hệ thống tập tin liên quan là ext4, vì vậy thay đổi kích thước trực tuyến được hỗ trợ; tuy nhiên, trong khi được gắn kết, các hệ thống tập tin chỉ có thể được phát triển. Để thu nhỏ phân vùng yêu cầu ngắt kết nối, tất nhiên điều này là không thể đối với phân vùng gốc trong hoạt động bình thường.

Các câu trả lời trên Web dường như xoay quanh việc khởi động LiveCD hoặc phương tiện cứu hộ khác, thực hiện thao tác thu nhỏ, sau đó khởi động lại vào hệ thống đã cài đặt. Tuy nhiên, hệ thống được đề cập là từ xa và tôi chỉ có quyền truy cập qua SSH. Tôi có thể khởi động lại, nhưng khởi động đĩa cứu hộ và thực hiện các thao tác từ bàn điều khiển là không thể.

Làm thế nào tôi có thể ngắt kết nối hệ thống tập tin gốc trong khi duy trì truy cập shell từ xa?


Bất kỳ cơ hội để tạm thời gắn hệ thống tập tin gốc trên một máy chủ khác? ví dụ: quay một VM khác và trình bày dung lượng đĩa này cho nó?
steve

Máy chủ là vật lý, vì vậy không.
Tom Hunt

4
Sao chép root vào tmpfs và pivot_rootvào đó. Một ví dụ ở đây dreamlayers.blogspot.co.uk/2012/10/rasty-linux-from-ram.html - thật khó khăn nhưng nếu bạn có một hộp thử nghiệm để thử, rất đáng để xem xét.
steve

1
Một ví dụ khác ở đây, nơi truy cập từ xa qua ssh được coi là ivarch.com/bloss/oss/2007/01/ trên
steve

2
Nếu LVM gốc đủ nhỏ, bạn có thể sao chép nó vào LVM khác và tạo boot eatery (mặc định mới tạm thời) trong grub để sử dụng nó, sau đó khởi động từ nó (biến nó thành "hệ thống trực tiếp" của bạn)
Rabin

Câu trả lời:


170

Để giải quyết vấn đề này, thông tin được cung cấp tại http://www.ivarch.com/bloss/oss/2007/01/resize-a-live-root-fs-a-howto.shtml là mấu chốt. Tuy nhiên, hướng dẫn đó dành cho một phiên bản rất cũ của RHEL và nhiều thông tin khác nhau đã lỗi thời.

Các hướng dẫn bên dưới được tạo để hoạt động với CentOS 7, nhưng chúng có thể dễ dàng đủ chuyển sang bất kỳ bản phân phối nào chạy systemd. Tất cả các lệnh được chạy như root.

  1. Đảm bảo hệ thống ở trạng thái ổn định

    Hãy chắc chắn rằng không có ai khác đang sử dụng nó và không có gì quan trọng khác đang diễn ra. Có lẽ nên dừng các đơn vị cung cấp dịch vụ như httpd hoặc ftpd, chỉ để đảm bảo các kết nối bên ngoài không phá vỡ mọi thứ ở giữa.

    systemctl stop httpd
    systemctl stop nfs-server
    # and so on....
    
  2. Ngắt kết nối tất cả các hệ thống tập tin không sử dụng

    umount -a
    

    Điều này sẽ in một số cảnh báo 'Target đang bận', cho chính khối lượng gốc và cho các FS tạm thời / hệ thống khác nhau. Đây có thể được bỏ qua cho thời điểm này. Điều quan trọng là không có hệ thống tập tin trên đĩa nào được gắn kết, ngoại trừ chính hệ thống tập tin gốc. Xác nhận điều này:

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

    Nếu bạn thấy bất kỳ hệ thống tập tin trên đĩa nào vẫn được gắn kết, thì cái gì đó vẫn đang chạy mà không nên. Kiểm tra xem nó đang sử dụng cái gì fuser:

    # if necessary:
    yum install psmisc
    # then:
    fuser -vm <mountpoint>
    systemctl stop <whatever>
    umount -a
    # repeat as required...
    
  3. Làm gốc tạm thời

    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/
    

    Điều này tạo ra một hệ thống gốc rất tối thiểu, phá vỡ (trong số những thứ khác) xem manpage (không /usr/share), tùy chỉnh ở cấp độ người dùng (không /roothoặc /home), v.v. Điều này là có chủ ý, vì nó cấu thành sự khuyến khích không ở trong một hệ thống gốc được bồi thẩm đoàn như vậy lâu hơn cần thiết.

    Tại thời điểm này, bạn cũng nên đảm bảo rằng tất cả các phần mềm cần thiết đã được cài đặt, vì nó cũng sẽ chắc chắn phá vỡ trình quản lý gói. Lướt qua tất cả các bước và đảm bảo bạn có các tệp thực thi cần thiết.

  4. Xoay vào gốc

    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 gây ra các mount để cho phép chia sẻ cây con theo mặc định (như với mount --make-shared) và điều này gây ra pivot_rootlỗi. Do đó, chúng tôi tắt nó trên toàn cầu với mount --make-rprivate /. Hệ thống và hệ thống tập tin tạm thời được chuyển bán buôn vào root mới. Điều này là cần thiết để làm cho nó hoạt động ở tất cả; các ổ cắm để liên lạc với systemd, trong số những thứ khác, sống trong đó /run, và vì vậy không có cách nào để làm cho các tiến trình chạy đóng nó.

  5. Đảm bảo truy cập từ xa sống sót sau khi chuyển đổi

    systemctl restart sshd
    systemctl status sshd
    

    Sau khi khởi động lại sshd, đảm bảo rằng bạn có thể vào, bằng cách mở một thiết bị đầu cuối khác và kết nối lại với máy thông qua ssh. Nếu bạn không thể, hãy khắc phục sự cố trước khi tiếp tục.

    Khi bạn đã xác minh, bạn có thể kết nối lại, thoát khỏi trình bao bạn đang sử dụng và kết nối lại. Điều này cho phép các ngã ba còn lại sshdthoát ra và đảm bảo cái mới không giữ /oldroot.

  6. Đóng mọi thứ vẫn sử dụng root cũ

    fuser -vm /oldroot
    

    Điều này sẽ in một danh sách các quy trình vẫn đang giữ trên thư mục gốc cũ. Trên hệ thống của tôi, nó trông như thế này:

                 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
    

    Bạn cần phải đối phó với từng quy trình trước khi bạn có thể ngắt kết nối /oldroot. Cách tiếp cận vũ phu chỉ đơn giản là kill $PIDcho mỗi người, nhưng điều này có thể phá vỡ mọi thứ. Để làm điều đó nhẹ nhàng hơn:

    systemctl | grep running
    

    Điều này tạo ra một danh sách các dịch vụ đang chạy. Bạn sẽ có thể tương quan điều này với danh sách các quy trình đang nắm giữ /oldroot, sau đó phát hành systemctl restartcho từng quy trình . Một số dịch vụ sẽ từ chối đưa ra trong thư mục gốc tạm thời và vào trạng thái không thành công; những điều này không thực sự quan trọng vào lúc này.

    Nếu ổ đĩa gốc bạn muốn thay đổi kích thước là ổ LVM, bạn cũng có thể cần phải khởi động lại một số dịch vụ đang chạy khác, ngay cả khi chúng không hiển thị trong danh sách được tạo bởi fuser -vm /oldroot. Nếu bạn thấy bạn không thể thay đổi kích thước ổ LVM trong Bước 7, hãy thử systemctl restart systemd-udevd.

    Một số quy trình không thể được xử lý thông qua đơn giản systemctl restart. Đối với tôi những thứ này bao gồm auditd(không muốn bị giết qua systemctl, và vì vậy chỉ muốn a kill -15). Đây có thể được giải quyết với cá nhân.

    Quá trình cuối cùng bạn sẽ tìm thấy, thường là systemdchính nó. Đối với điều này, chạy systemctl daemon-reexec.

    Khi bạn đã hoàn tất, bảng sẽ trông như thế này:

                 USER        PID ACCESS COMMAND
    /oldroot:    root     kernel mount /oldroot
    
  7. Tháo gốc

    umount /oldroot
    

    Tại thời điểm này, bạn có thể thực hiện bất kỳ thao tác nào bạn yêu cầu. Câu hỏi ban đầu cần một resize2fslời mời đơn giản , nhưng bạn có thể làm bất cứ điều gì bạn muốn ở đây; một trường hợp sử dụng khác là chuyển hệ thống tập tin gốc từ một phân vùng đơn giản sang LVM / RAID / bất cứ điều gì.

  8. Xoay gốc trở lại

    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
    

    Đây là một sự đảo ngược đơn giản của bước 4.

  9. Vứt bỏ gốc tạm thời

    Lặp lại các bước 5 và 6, ngoại trừ sử dụng /tmp/tmprootthay thế /oldroot. Sau đó:

    umount /tmp/tmproot
    rmdir /tmp/tmproot
    

    Vì nó là một tmpfs, tại thời điểm này, gốc tạm thời tan vào ether, không bao giờ được nhìn thấy nữa.

  10. Đặt mọi thứ trở lại vị trí của họ

    Mount hệ thống tập tin một lần nữa:

    mount -a
    

    Tại thời điểm này, bạn cũng nên cập nhật /etc/fstabgrub.cfgphù hợp với bất kỳ điều chỉnh nào bạn đã thực hiện trong bước 7.

    Khởi động lại bất kỳ dịch vụ thất bại:

    systemctl | grep failed
    systemctl restart <whatever>
    

    Cho phép chia sẻ lại một lần nữa:

    mount --make-rshared /
    

    Bắt đầu các đơn vị dịch vụ đã dừng - bạn có thể sử dụng lệnh đơn này:

    systemctl isolate default.target
    

Và bạn đã hoàn thành.

Rất cám ơn Andrew Wood, người đã thực hiện quá trình tiến hóa này trên RHEL4 và steve, người đã cung cấp cho tôi liên kết đến cái trước.


11
Câu trả lời tuyệt vời. Gần như huyền diệu, và rất rõ ràng và đơn giản. Sử dụng nó với VPS debian mà không có bất kỳ vấn đề nào ( umount /oldroot/boottất nhiên là phải ở giai đoạn 6). Tôi đang liên kết câu trả lời của bạn với các câu hỏi SE khác không có câu trả lời hoặc câu trả lời phủ định.
vaab

3
Và đã giải quyết, vấn đề đã được @vaab chỉ ra; bạn phải umount /oldroot/boottrước bạnumount /oldroot
ToBeRepliated

3
Vấn đề là ngắt kết nối và thao tác hệ thống tập tin gốc mà không cần bàn điều khiển vật lý. Theo tôi biết, không có cách nào để mở một dịch vụ đọc từ một phân vùng trong khi ngắt kết nối phân vùng đó. Nếu dịch vụ của bạn không chạm vào FS gốc, có thể bạn có thể mở nó bằng cách sử dụng mount --movevào các tmpfs, nhưng điều đó không được hỗ trợ.
Tom Hunt

2
Bạn cần sử dụng các tiện ích hệ điều hành để khởi động lại daemon init. Tôi chưa bao giờ sử dụng mới bắt đầu, nhưng wiki.ubfox.com/FoundationsTeam/Specs/ khuyên gợi ý rằng telinit ucó thể làm những gì bạn muốn.
Tom Hunt

3
Một nếp nhăn bổ sung mà tôi gặp phải: / tmp là một ramdisk trên hệ thống của tôi, vì vậy tôi đã kết thúc với một ramdisk được gắn vào /oldroot/tmp, điều đó ngăn tôi không thể đếm được /oldroot, nhưng không hiển thị fuserhoặc lsofxuất ra. Mất một chút nhìn chằm chằm vào systemd để tìm ra cái đó ...
Chris Kitching

7

Nếu bạn chắc chắn những gì bạn đang làm - do đó không thử nghiệm, bạn có thể kết nối với initrd, đây là cách không tương tác và nhanh chóng.

Trên hệ thống dựa trên Debian ở đây là như thế nào.

Xem mã: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-resizefs.sh

Có một ví dụ khác: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-convert-ext3-ext4.sh



1
Đây là một cách tiếp cận âm thanh. Tôi thích của tôi vì đã để tôi thực hiện các thao tác cần thiết một cách tương tác; tuy nhiên, cái này có lẽ nhanh hơn Có thể tốt để chỉnh sửa thêm một số chi tiết vào câu trả lời hoặc xem xét các nền tảng khác (có vẻ như cách tiếp cận chung này vẫn sẽ hoạt động với dracut hoặc mkinitcpio hoặc bất kỳ trình tạo initramfs hiện đại mơ hồ nào khác).
Tom Hunt

Xin lỗi @ stephen-rauch Tôi chỉ nêu ra ý tưởng không phải là thực thi.
Szépe Viktor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.