web-dev-qa-db-ja.com

livecdを起動せずにルートファイルシステムを縮小する方法

以前にルートファイルシステムの下にあったデータを専用のマウントポイントに移動するには、システムのパーティションを再配置する必要があることに気づきました。ボリュームはすべてLVMにあるため、これは比較的簡単です。新しいボリュームを作成し、そこにデータを移動し、ルートファイルシステムを縮小してから、適切なポイントに新しいボリュームをマウントします。

問題はステップ3で、ルートファイルシステムを縮小します。関連するファイルシステムはext4であるため、オンラインでのサイズ変更がサポートされています。ただし、マウントされている間は、ファイルシステムを拡張することしかできません。パーティションを縮小するには、それをアンマウントする必要がありますが、通常の操作ではルートパーティションではこれは不可能です。

Webに関する回答は、LiveCDまたはその他のレスキューメディアの起動、縮小操作の実行、インストールされたシステムへの再起動に関係しているようです。ただし、問題のシステムはリモートであり、SSH経由でのみアクセスできます。再起動はできますが、レスキューディスクを起動してコンソールから操作することはできません。

リモートシェルアクセスを維持しながらルートファイルシステムをマウント解除するにはどうすればよいですか?

100
Tom Hunt

この問題を解決する際、 http://www.ivarch.com/blogs/oss/2007/01/resize-a-live-root-fs-a-howto.shtml で提供された情報は、極めて重要です。ただし、そのガイドは非常に古いバージョンのRHEL用であり、さまざまな情報が古くなりました。

以下の手順はCentOS 7で動作するように作成されていますが、systemdを実行するすべてのディストリビューションに簡単に転送できるはずです。すべてのコマンドはrootとして実行されます。

  1. システムが安定した状態であることを確認します

    他の誰もそれを使用していないこと、そして他に重要なことは何も起こっていないことを確認してください。外部接続によって途中で混乱が生じないようにするために、httpdやftpdなどのサービス提供ユニットを停止することをお勧めします。

    systemctl stop httpd
    systemctl stop nfs-server
    # and so on....
    
  2. 未使用のファイルシステムをすべてマウント解除します

    umount -a
    

    これにより、ルートボリューム自体およびさまざまな一時/システムFSについて、「ターゲットがビジーです」という警告が表示されます。現時点ではこれらは無視できます。重要なのは、ルートファイルシステム自体を除いて、ディスク上のファイルシステムがマウントされたままにならないことです。これを確認してください:

    # 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を試してください。

    一部のプロセスは、単純なsystemctl restartでは処理できません。私にとっては、これらにはauditdが含まれていました(これはsystemctlを介して殺されることを好まないため、kill -15が必要でした)。これらは個別に処理できます。

    あなたが見つける最後のプロセスは、通常、systemd自体です。これには、systemctl daemon-reexecを実行します。

    完了すると、テーブルは次のようになります。

                 USER        PID ACCESS COMMAND
    /oldroot:    root     kernel mount /oldroot
    
  7. 古いルートをアンマウントします

    umount /oldroot
    

    この時点で、必要な操作を実行できます。元の質問では単純なresize2fsの呼び出しが必要でしたが、ここでは何でも好きなことができます。もう1つの使用例は、ルートファイルシステムを単純なパーティションから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の代わりに/oldrootを使用する以外は、手順5と6を繰り返します。次に:

    umount /tmp/tmproot
    rmdir /tmp/tmproot
    

    これはtmpfsなので、この時点で一時的なルートはエーテルに溶解し、二度と表示されることはありません。

  10. 物を元の場所に戻す

    ファイルシステムを再度マウントします。

    mount -a
    

    この時点で、手順7で行った調整に従って/etc/fstabおよびgrub.cfgも更新する必要があります。

    失敗したサービスを再起動します。

    systemctl | grep failed
    systemctl restart <whatever>
    

    共有サブツリーを再び許可:

    mount --make-rshared /
    

    停止したサービスユニットを開始します。次の1つのコマンドを使用できます。

    systemctl isolate default.target
    

これで完了です。

RHEL4でこの進化を実現したAndrew Woodと、前者へのリンクを提供してくれたsteveに感謝します。

182
Tom Hunt

何をやっているのかがわかっている場合-実験を行わない場合は、非対話的で高速な方法であるinitrdを使用できます。

Debianベースのシステムでは、ここにその方法があります。

コードを参照してください: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-setup/debian-resizefs.sh

別の例があります: https://github.com/szepeviktor/debian-server-tools/blob/master/debian-setup/debian-convert-ext3-ext4.sh

10
Szépe Viktor

DigitalOcean VPS(ルートとして25G/dev/vda1がマウントされている)で私がしたこと:

  1. fdiskを使用して、最初の(25G)パーティションを削除する
  2. 20Gパーティションを作成します(最初のセクターは元のセクターと同じである必要があります)
  3. 新しいパーティションを作成します(明らかにサイズが5Gです)、/ dev/vda2になります。
  4. パーティションテーブルを書き込み、fdiskを終了します。
  5. / dev/vda2にext4ファイルシステムを作成します
  6. 両方のパーティションのUUIDに注意してください(ls -l/dev/disk/by-uuid)
  7. /boot/grub/grub.cfgおよび/ etc/fstabの/ dev/vda1 UUIDを/ dev/vda2 UUIDに置き換えます
  8. / dev/vda2を/ mntにマウントします
  9. /から/ mntに(dev、proc、run、sys、mntを除く)すべてをコピーします
  10. 実行update-grub
  11. rebootと祈る

上記はresize2fsがサポートされていないと言われたときにうまくいきました。

0
Zsombor