Cara mengecilkan filesystem root tanpa mem-boot sebuah livecd

93

Saya menemukan diri saya perlu mengatur ulang partisi sistem untuk memindahkan data sebelumnya di bawah sistem file root ke titik mount khusus. Volume semuanya ada di LVM, jadi ini relatif mudah: buat volume baru, pindahkan data ke dalamnya, menyusutkan sistem file root, lalu pasang volume baru di titik yang sesuai.

Masalahnya adalah langkah 3, menyusutkan sistem file root. Sistem file yang terlibat adalah ext4, jadi pengubahan ukuran online didukung; namun, ketika di-mount, sistem file hanya bisa ditanam. Untuk mengecilkan partisi diperlukan unmount, yang tentu saja tidak mungkin untuk partisi root dalam operasi normal.

Jawaban di sekitar Web tampaknya berputar di sekitar mem-boot LiveCD atau media penyelamat lainnya, melakukan operasi menyusut, lalu mem-boot kembali ke sistem yang diinstal. Namun, sistem yang dimaksud adalah jarak jauh, dan saya hanya memiliki akses melalui SSH. Saya dapat reboot, tetapi mem-boot disk cadangan dan melakukan operasi dari konsol tidak dimungkinkan.

Bagaimana saya bisa melepas sistem file root dengan tetap mempertahankan akses shell jarak jauh?

Tom Hunt
sumber
Adakah kesempatan untuk sementara memasang sistem file root di server yang berbeda? misalnya memutar VM lain dan menyajikan volume disk ini ke sana?
steve
Server bersifat fisik, jadi tidak.
Tom Hunt
4
Salin root ke tmpfs dan pivot_rootke sana. Contoh di sini dreamlayers.blogspot.co.uk/2012/10/running-linux-from-ram.html - rumit tetapi jika Anda memiliki kotak tes untuk mencobanya, patut dipertimbangkan.
steve
1
Contoh lain di sini, di mana akses jarak jauh melalui ssh dianggap ivarch.com/blogs/oss/2007/01/…
steve
2
Jika root LVM cukup kecil, Anda dapat mengkloningnya ke LVM lain dan membuat restoran boot (temp new default) di grub untuk menggunakannya, lalu boot darinya (menjadikannya "sistem langsung")
Rabin

Jawaban:

170

Dalam mengatasi masalah ini, informasi yang disediakan di http://www.ivarch.com/blogs/oss/2007/01/resize-a-live-root-fs-a-howto.shtml sangat penting. Namun, panduan itu adalah untuk versi RHEL yang sangat lama, dan berbagai informasi sudah usang.

Instruksi di bawah ini dibuat untuk bekerja dengan CentOS 7, tetapi mereka harus cukup mudah ditransfer ke distro yang menjalankan systemd. Semua perintah dijalankan sebagai root.

  1. Pastikan sistem dalam kondisi stabil

    Pastikan tidak ada orang lain yang menggunakannya dan tidak ada hal lain yang penting sedang terjadi. Mungkin ide yang bagus untuk menghentikan unit penyedia layanan seperti httpd atau ftpd, hanya untuk memastikan koneksi eksternal tidak mengganggu hal-hal di tengah.

    systemctl stop httpd
    systemctl stop nfs-server
    # and so on....
    
  2. Lepas semua sistem file yang tidak digunakan

    umount -a
    

    Ini akan mencetak sejumlah peringatan 'Target is busy', untuk volume root itu sendiri dan untuk berbagai FS sementara / sistem. Ini dapat diabaikan untuk saat ini. Yang penting adalah bahwa tidak ada sistem file pada disk yang tetap terpasang, kecuali sistem file root itu sendiri. Verifikasikan ini:

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

    Jika Anda melihat sistem file pada disk masih terpasang, maka sesuatu masih berjalan yang seharusnya tidak. Periksa apa yang digunakan fuser:

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

    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/
    

    Ini menciptakan sistem root yang sangat minimal, yang memecah (antara lain) melihat halaman manual (tidak /usr/share), kustomisasi tingkat pengguna (tidak /rootatau /home) dan sebagainya. Ini disengaja, karena merupakan dorongan untuk tidak tinggal di sistem root seperti juri lebih lama dari yang diperlukan.

    Pada titik ini, Anda juga harus memastikan bahwa semua perangkat lunak yang diperlukan telah diinstal, karena itu juga akan menghancurkan manajer paket. Lihatlah semua langkah, dan pastikan Anda memiliki executable yang diperlukan.

  4. Putar ke root

    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 menyebabkan mount untuk memungkinkan berbagi subtree secara default (seperti dengan mount --make-shared), dan ini menyebabkan pivot_rootgagal. Karenanya, kami mematikannya secara global mount --make-rprivate /. Sistem dan sistem file sementara dipindahkan secara grosir ke root baru. Ini diperlukan untuk membuatnya berfungsi sama sekali; soket untuk komunikasi dengan systemd, antara lain, tinggal di /rundalamnya, dan dengan demikian tidak ada cara untuk membuat proses yang berjalan menutupnya.

  5. Pastikan akses jarak jauh selamat dari pergantian tersebut

    systemctl restart sshd
    systemctl status sshd
    

    Setelah memulai kembali sshd, pastikan Anda dapat masuk, dengan membuka terminal lain dan menghubungkan ke mesin lagi melalui ssh. Jika tidak bisa, perbaiki masalah sebelum melanjutkan.

    Setelah memverifikasi, Anda dapat terhubung lagi, keluar dari shell yang saat ini Anda gunakan dan sambungkan kembali. Ini memungkinkan garpu yang tersisa sshduntuk keluar dan memastikan yang baru tidak tertahan /oldroot.

  6. Tutup semuanya masih menggunakan root yang lama

    fuser -vm /oldroot
    

    Ini akan mencetak daftar proses yang masih berpegang pada direktori root yang lama. Di sistem saya, tampilannya seperti ini:

                 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
    

    Anda harus berurusan dengan masing-masing dari proses ini sebelum Anda dapat meng-unmount /oldroot. Pendekatan brute-force hanya kill $PIDuntuk masing-masing, tetapi ini dapat merusak banyak hal. Untuk melakukannya dengan lebih lembut:

    systemctl | grep running
    

    Ini membuat daftar layanan yang berjalan. Anda harus dapat menghubungkan ini dengan daftar proses yang ada /oldroot, kemudian mengeluarkan systemctl restartuntuk masing-masing proses. Beberapa layanan akan menolak untuk muncul di root sementara dan memasuki kondisi gagal; ini tidak terlalu penting untuk saat ini.

    Jika root drive yang ingin Anda ubah ukurannya adalah drive LVM, Anda mungkin juga perlu me-restart beberapa layanan lain yang berjalan, bahkan jika mereka tidak muncul dalam daftar yang dibuat oleh fuser -vm /oldroot. Jika ternyata Anda tidak dapat mengubah ukuran drive LVM pada Langkah 7, coba systemctl restart systemd-udevd.

    Beberapa proses tidak dapat ditangani dengan sederhana systemctl restart. Bagi saya ini termasuk auditd(yang tidak suka dibunuh via systemctl, dan hanya ingin a kill -15). Ini dapat ditangani secara individual.

    Proses terakhir yang Anda temukan, biasanya, adalah systemddirinya sendiri. Untuk ini, jalankan systemctl daemon-reexec.

    Setelah selesai, tabel akan terlihat seperti ini:

                 USER        PID ACCESS COMMAND
    /oldroot:    root     kernel mount /oldroot
    
  7. Lepas root yang lama

    umount /oldroot
    

    Pada titik ini, Anda dapat melakukan manipulasi apa pun yang Anda butuhkan. Pertanyaan aslinya membutuhkan resize2fsdoa sederhana , tetapi Anda dapat melakukan apa pun yang Anda inginkan di sini; satu use case lainnya adalah mentransfer filesystem root dari partisi sederhana ke LVM / RAID / apa pun.

  8. Putar kembali root

    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
    

    Ini adalah pembalikan langsung dari langkah 4.

  9. Buang akar sementara

    Ulangi langkah 5 dan 6, kecuali menggunakan /tmp/tmprootdi tempat /oldroot. Kemudian:

    umount /tmp/tmproot
    rmdir /tmp/tmproot
    

    Karena ini adalah tmpfs, pada titik ini root sementara larut ke dalam eter, tidak pernah terlihat lagi.

  10. Kembalikan semuanya ke tempatnya masing-masing

    Pasang kembali sistem file:

    mount -a
    

    Pada titik ini, Anda juga harus memperbarui /etc/fstabdan grub.cfgsesuai dengan penyesuaian yang Anda buat selama langkah 7.

    Mulai ulang layanan yang gagal:

    systemctl | grep failed
    systemctl restart <whatever>
    

    Izinkan sub pohon yang dibagikan lagi:

    mount --make-rshared /
    

    Mulai unit layanan yang dihentikan - Anda dapat menggunakan perintah tunggal ini:

    systemctl isolate default.target
    

Dan kamu sudah selesai.

Terima kasih banyak kepada Andrew Wood, yang telah mengerjakan evolusi ini di RHEL4, dan steve, yang memberi saya tautan ke yang sebelumnya.

Tom Hunt
sumber
11
Jawaban yang luar biasa. Hampir magis, dan sangat jelas dan lugas. Digunakan dengan debian VPS tanpa masalah (hanya harus umount /oldroot/boot, pada tahap 6). Saya menghubungkan jawaban Anda ke pertanyaan SE lain yang tidak memiliki jawaban atau jawaban negatif.
vaab
3
Dan diselesaikan, masalahnya adalah seperti yang ditunjukkan @vaab; Anda harus umount /oldroot/bootsebelum Andaumount /oldroot
ToBeReplaced
3
Intinya adalah untuk meng-unmount dan memanipulasi sistem file root tanpa memerlukan konsol fisik. Sejauh yang saya tahu, tidak ada cara untuk tetap membuka layanan yang membaca dari sebuah partisi sambil melepas partisi itu. Jika layanan Anda tidak menyentuh FS root, mungkin Anda bisa tetap menggunakannya menggunakan mount --movetmpfs, tetapi itu tidak didukung.
Tom Hunt
2
Anda perlu menggunakan fasilitas OS untuk me-restart daemon init. Saya tidak pernah menggunakan pemula, tetapi wiki.ubuntu.com/FoundationsTeam/Specs/… menyarankan yang telinit umungkin melakukan apa yang Anda inginkan.
Tom Hunt
3
Kerut tambahan yang saya temui: / tmp adalah ramdisk di sistem saya, jadi saya berakhir dengan ramdisk yang dipasang di /oldroot/tmp, yang mencegah saya unmount /oldroot, tetapi tidak muncul fuseratau keluar lsof. Butuh sedikit menatap systemd untuk mengerjakan yang keluar ...
Chris Kitching
7

Jika Anda yakin apa yang Anda lakukan - sehingga tidak bereksperimen, Anda dapat menggunakan initrd yang merupakan cara non-interaktif dan cepat.

Pada sistem berbasis Debian di sini adalah caranya.

Lihat kode: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-resizefs.sh

Ada contoh lain: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-convert-ext3-ext4.sh

Szépe Viktor
sumber
Ketika memberikan jawaban, lebih baik memberi penjelasan mengapa MENGAPA jawaban Anda adalah jawabannya .
Stephen Rauch
1
Ini adalah pendekatan yang bagus. Saya suka milik saya karena membiarkan saya melakukan manipulasi yang diperlukan secara interaktif; Namun, ini mungkin lebih cepat. Mungkin lebih baik untuk mengedit beberapa rincian lebih lanjut ke dalam jawaban itu sendiri, atau untuk mempertimbangkan platform lain (tampaknya pendekatan umum ini masih bekerja dengan dracut atau mkinitcpio atau generator initramfs modern lain yang samar-samar modern).
Tom Hunt
Maaf @ stephen-rauch saya hanya menunjukkan ide bukan eksekusi.
Szépe Viktor