Come ridurre il filesystem di root senza avviare un livecd


94

Mi ritrovo a dover riorganizzare le partizioni di un sistema per spostare i dati precedentemente sotto il filesystem di root in punti di montaggio dedicati. I volumi sono tutti in LVM, quindi è relativamente semplice: creare nuovi volumi, spostare i dati in essi, ridurre il filesystem di root, quindi montare i nuovi volumi nei punti appropriati.

Il problema è il passaggio 3, che riduce il filesystem di root. I filesystem coinvolti sono ext4, quindi è supportato il ridimensionamento online; tuttavia, mentre montato, i filesystem possono essere solo cresciuti. Per ridurre la partizione è necessario smontarla, cosa che ovviamente non è possibile per la partizione root durante il normale funzionamento.

Le risposte sul Web sembrano ruotare all'avvio di un LiveCD o di altri supporti di salvataggio, eseguendo l'operazione di riduzione, quindi riavviando nel sistema installato. Tuttavia, il sistema in questione è remoto e ho accesso solo tramite SSH. Posso riavviare, ma non è possibile avviare un disco di ripristino ed eseguire operazioni dalla console.

Come posso smontare il filesystem di root mantenendo l'accesso remoto alla shell?


Qualche opportunità per montare temporaneamente il filesystem di root su un altro server? ad esempio far girare un'altra VM e presentare questo volume del disco ad essa?
Steve

Il server è fisico, quindi no.
Tom Hunt,

4
Copia root su tmpfs e pivot_rootlì. Un esempio qui dreamlayers.blogspot.co.uk/2012/10/running-linux-from-ram.html - è complicato ma se hai una scatola di prova per provarlo, vale la pena considerare.
steve

1
Un altro esempio qui, in cui l'accesso remoto tramite ssh è considerato ivarch.com/blogs/oss/2007/01/…
steve

2
Se il LVM di root è abbastanza piccolo puoi clonarlo su un altro LVM e creare boot eatery (temp new default) in grub per usarlo, e quindi avviare da esso (rendendolo il tuo "sistema live")
Rabin

Risposte:


171

Nel risolvere questo problema, le informazioni fornite su http://www.ivarch.com/blogs/oss/2007/01/resize-a-live-root-fs-a-howto.shtml sono state fondamentali. Tuttavia, quella guida è per una versione molto vecchia di RHEL e varie informazioni erano obsolete.

Le seguenti istruzioni sono concepite per funzionare con CentOS 7, ma dovrebbero essere facilmente trasferibili su qualsiasi distribuzione che esegua systemd. Tutti i comandi vengono eseguiti come root.

  1. Assicurarsi che il sistema sia in uno stato stabile

    Assicurati che nessun altro lo stia usando e che non stia succedendo niente di importante. È probabilmente una buona idea interrompere le unità che forniscono servizi come httpd o ftpd, solo per garantire che le connessioni esterne non interrompano le cose nel mezzo.

    systemctl stop httpd
    systemctl stop nfs-server
    # and so on....
    
  2. Smonta tutti i filesystem inutilizzati

    umount -a
    

    Ciò stamperà una serie di avvisi "Destinazione occupata", per il volume radice stesso e per vari FS temporanei / di sistema. Questi possono essere ignorati per il momento. Ciò che è importante è che nessun filesystem su disco rimanga montato, tranne il filesystem di root stesso. Verifica questo:

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

    Se vedi ancora dei filesystem su disco montati, qualcosa è ancora in esecuzione che non dovrebbe essere. Controlla cosa sta usando fuser:

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

    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/
    

    Questo crea un sistema di root molto minimale, che interrompe (tra le altre cose) la visualizzazione della manpage (no /usr/share), le personalizzazioni a livello di utente (no /rooto /home) e così via. Questo è intenzionale, in quanto costituisce un incoraggiamento a non rimanere in un sistema di root truccato dalla giuria più del necessario.

    A questo punto dovresti anche assicurarti che tutto il software necessario sia installato, in quanto interromperà sicuramente il gestore dei pacchetti. Dai un'occhiata a tutti i passaggi e assicurati di disporre degli eseguibili necessari.

  4. Pivot nella radice

    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 fa sì che i montaggi consentano la condivisione delle sottostrutture per impostazione predefinita (come con mount --make-shared) e ciò causa un pivot_rooterrore. Quindi, lo disattiviamo a livello globale con mount --make-rprivate /. I filesystem di sistema e temporanei vengono spostati all'ingrosso nella nuova radice. Questo è necessario per farlo funzionare affatto; le prese per la comunicazione con systemd, tra le altre cose, vivono /rune quindi non c'è modo di far chiudere i processi in esecuzione.

  5. Assicurarsi che l'accesso remoto sia sopravvissuto al passaggio all'euro

    systemctl restart sshd
    systemctl status sshd
    

    Dopo aver riavviato sshd, assicurarsi di poter accedere, aprendo un altro terminale e connettendosi nuovamente alla macchina tramite ssh. Se non ci riesci, risolvi il problema prima di proseguire.

    Dopo aver verificato, è possibile riconnettersi, uscire dalla shell attualmente in uso e riconnettersi. Ciò consente al rimanente biforcuto sshddi uscire e garantisce che quello nuovo non trattiene /oldroot.

  6. Chiudi tutto ancora usando la vecchia radice

    fuser -vm /oldroot
    

    Verrà stampato un elenco di processi ancora presenti nella vecchia directory principale. Sul mio sistema, sembrava così:

                 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
    

    È necessario gestire ciascuno di questi processi prima di poter smontare /oldroot. L'approccio della forza bruta è semplicemente kill $PIDper ciascuno, ma questo può spezzare le cose. Per farlo più dolcemente:

    systemctl | grep running
    

    Questo crea un elenco di servizi in esecuzione. Dovresti essere in grado di correlarlo con l'elenco dei processi in attesa /oldroot, quindi emettere systemctl restartper ciascuno di essi. Alcuni servizi si rifiuteranno di entrare nella radice temporanea e di entrare in uno stato fallito; questi non contano davvero per il momento.

    Se l'unità principale che si desidera ridimensionare è un'unità LVM, potrebbe essere necessario riavviare alcuni altri servizi in esecuzione, anche se non vengono visualizzati nell'elenco creato da fuser -vm /oldroot. Se non riesci a ridimensionare un'unità LVM al punto 7, prova systemctl restart systemd-udevd.

    Alcuni processi non possono essere gestiti in modo semplice systemctl restart. Per me questi inclusi auditd(a cui non piace essere ucciso tramite systemctl, e quindi volevo solo un kill -15). Questi possono essere trattati individualmente.

    L'ultimo processo che troverai, di solito, è systemdse stesso. Per questo, corri systemctl daemon-reexec.

    Una volta terminato, la tabella dovrebbe apparire così:

                 USER        PID ACCESS COMMAND
    /oldroot:    root     kernel mount /oldroot
    
  7. Smonta la vecchia radice

    umount /oldroot
    

    A questo punto, è possibile eseguire qualsiasi manipolazione richiesta. La domanda originale aveva bisogno di una semplice resize2fsinvocazione, ma puoi fare quello che vuoi qui; un altro caso d'uso è il trasferimento del filesystem di root da una semplice partizione a LVM / RAID / qualunque cosa.

  8. Riporta indietro la radice

    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
    

    Questa è un'inversione semplice del passaggio 4.

  9. Smaltire la radice temporanea

    Ripetere i passaggi 5 e 6, ad eccezione dell'uso /tmp/tmprootal posto di /oldroot. Poi:

    umount /tmp/tmproot
    rmdir /tmp/tmproot
    

    Essendo un tmpfs, a questo punto la radice temporanea si dissolve nell'etere, per non essere mai più vista.

  10. Metti le cose al loro posto

    Montare nuovamente i filesystem:

    mount -a
    

    A questo punto, è necessario anche aggiornare /etc/fstabe grub.cfgin conformità con eventuali modifiche apportate durante il passaggio 7.

    Riavvia eventuali servizi non riusciti:

    systemctl | grep failed
    systemctl restart <whatever>
    

    Consenti nuovamente sottotitoli condivisi:

    mount --make-rshared /
    

    Avviare le unità di servizio arrestate: è possibile utilizzare questo comando singolo:

    systemctl isolate default.target
    

E hai finito.

Mille grazie a Andrew Wood, che ha elaborato questa evoluzione su RHEL4, e Steve, che mi ha fornito il collegamento con il primo.


11
Risposta fantastica. Quasi magico, molto chiaro e diretto. Usata con VPS debian senza problemi (dovevo umount /oldroot/bootovviamente, sul palco 6). Sto collegando la tua risposta ad altre domande SE che non hanno avuto risposta o risposta negativa.
vaab,

3
E risolto, il problema era come indicato da @vaab; devi umount /oldroot/bootprima di teumount /oldroot
ToBe Sostituito

3
Il punto è smontare e manipolare il filesystem di root senza bisogno di una console fisica. Per quanto ne so, non c'è modo di tenere aperto un servizio che legge da una partizione mentre si smonta quella partizione. Se il tuo servizio non tocca il root FS, è possibile che tu possa tenerlo aperto usando mount --movein tmpfs, ma questo non è supportato.
Tom Hunt,

2
È necessario utilizzare le funzionalità del sistema operativo per riavviare il demone init. Non ho mai usato upstart, ma wiki.ubuntu.com/FoundationsTeam/Specs/… suggerisce che telinit upotrebbe fare quello che vuoi.
Tom Hunt,

3
Un ulteriore rughe mi sono imbattuto in: / tmp è un ramdisk sul mio sistema, quindi ho finito con un ramdisk montato /oldroot/tmp, il che mi ha impedito di smontare /oldroot, ma non viene visualizzato in fusero lsofdi uscita. Mi sono messo un po 'a fissare systemd per risolverlo ...
Chris Kitching,

7

Se sei sicuro di ciò che stai facendo, quindi non sperimentando, puoi collegarti a initrd che è il modo non interattivo e veloce.

Su un sistema basato su Debian ecco come.

Vedi il codice: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-resizefs.sh

C'è un altro esempio: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-convert-ext3-ext4.sh


Quando dai una risposta è preferibile dare una spiegazione del PERCHÉ la tua risposta è quella.
Stephen Rauch,

1
Questo è un approccio valido. Mi piace il mio per avermi permesso di fare le manipolazioni necessarie in modo interattivo; tuttavia, questo è probabilmente più veloce. Potrebbe essere utile modificare qualche dettaglio in più nella risposta stessa o considerare altre piattaforme (sembra che questo approccio generale funzionerebbe ancora con dracut o mkinitcpio o qualsiasi altro generatore di initramfs vagamente moderno).
Tom Hunt,

Scusa @ stephen-rauch, stavo solo sottolineando l'idea, non l'esecuzione.
Szépe Viktor,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.