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


93

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

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

Webに関する回答は、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でブート飲食店(temp new default)を作成し、それからブート(「ライブシステム」にする)
Rabin

回答:


170

この問題を解決するには、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に対して、多数の「ターゲットがビジーです」という警告が出力されます。現時点ではこれらは無視できます。重要なのは、ルートファイルシステム自体を除き、ディスク上のファイルシステムがマウントされていないことです。これを確認してください:

    # 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/
    

    これにより、非常に最小限のルートシステムが作成され、(特に)マンページの表示(no /usr/share)、ユーザーレベルのカスタマイズ(no /rootまたは/home)などが中断されます。これは意図的なものであり、必要に応じてそのようなju審員が管理するルートシステムにとどまらないように奨励するものです。

    この時点で、必要なソフトウェアがすべてインストールされていることも確認する必要があります。これにより、パッケージマネージャーも確実に破損します。すべての手順を一目見ながら、必要な実行可能ファイルがあることを確認してください。

  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
    

    これにより、実行中のサービスのリストが作成されます。これを保持しているプロセスのリストと相関させてから/oldrootsystemctl 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呼び出しが必要でしたが、ここでは何でもできます。もう1つのユースケースは、ルートファイルシステムを単純なパーティションからLVM / RAID / whateverに転送することです。

  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
    

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

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

    systemctl | grep failed
    systemctl restart <whatever>
    

    共有サブツリーを再度許可します。

    mount --make-rshared /
    

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

    systemctl isolate default.target
    

これで完了です。

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


11
素晴らしい答え。ほぼ魔法のようで、非常に明確でわかりやすい。debian VPSで問題なく使用しました(umount /oldroot/bootもちろん、ステージ6で必要でした)。あなたの答えを、回答も否定的な答えもなかった他のSEの質問にリンクしています。
vaab

3
そして解決した問題は、@ vaabが示したとおりでした。あなたはあなたのumount /oldroot/boot前にumount /oldroot
ToBeReplaced

3
ポイントは、物理コンソールを必要とせずにルートファイルシステムをアンマウントして操作することです。私の知る限り、パーティションのマウントを解除しながらパーティションから読み取るサービスを開いたままにする方法はありません。サービスがルートFSに触れない場合mount --moveは、tmpfs を使用して開いたままにしておくことができますが、サポートされていません。
トム・ハント

2
initデーモンを再起動するには、OS機能を使用する必要があります。私はupstartを使用したことはありませんが、wiki.ubuntu.com / FoundationsTeam / Specs / ...は、telinit uあなたが望むことをするかもしれないことを示唆しています。
トム・ハント

3
私はに走った追加のしわ:/ tmpが私のシステム上のRAMディスクであるので、私はに装着されたRAMディスクになってしまった/oldroot/tmpアンマウントから私を妨げ、/oldrootしかしに表示されませんfuserまたはlsof出力。...その1を動作するようにsystemdに見つめてのビットを取った
クリスKitching

7

自分が何をしているのかが確かな場合、つまり実験ではなく、非インタラクティブで高速な方法であるinitrdにフックすることができます。

Debianベースのシステムでの方法は次のとおりです。

コードを参照してください: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


答えを出すとき、あなたの答えがその理由である理由について説明することが望ましいです。
スティーブンラウチ

1
これは適切なアプローチです。インタラクティブに必要な操作をさせてくれたのが私の好みです。ただし、これはおそらくより高速です。回答自体をさらに詳細に編集するか、他のプラットフォームを検討することをお勧めします(この一般的なアプローチは、dracut、mkinitcpio、または他の漠然と近代的なinitramfsジェネレーターでも機能するようです)。
トム・ハント

@ stephen-rauch申し訳ありませんが、実行ではなくアイデアを指摘しただけです。
Szépeヴィクトル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.