morimorihogeです。涼しくなってきましたね、ありがたい。今日は小ネタです。
昔々から動いているサーバーのメンテナンスというのはいつになっても無くならないものです。新規で立てたサービスなんかはコンテナオーケストレーションサービス(AWS ECSやらk8sなど)に載せていても、数年前(5年前overレベル)に構築した環境などだと今でもSSHしてメンテするシステムはどの会社にもそれなりに転がっていることでしょう。
今日は、そんなサーバー環境が死にかけたときに使えるかもしれない話です。
ディスク障害とread-onlyマウント起動
Linuxではディストリビューションにもよるかもしれませんが、何らかの事情でルートファイルシステムにディスク障害が発生した場合、read-onlyモードでマウントされた状態でOSが起動します。
この状態になっているとあらゆるファイルシステムへの書き込みが失敗するため、何をやっても cannot create temp file for here-document: Read-only file system
といったエラーメッセージが出るようになってしまいます。
read-onlyでマウントされているかは起動時のメッセージなどにも表示されるとは思いますが、そもそもログが確認できない状態の場合などはmount
コマンドで実際にread-onlyでマウントされているかを確認することができます。
以下の例では /
である /dev/sda2
が ro
、つまりRead Onlyでマウントされていることが分かります(通常は rw
(Read-Write)となっているはず)。
root@example:~/composes# mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
(略)
/dev/sda2 on / type ext4 (ro,relatime,data=ordered)
(略)
ファイルをサルベージしたいが・・・これって詰んでる?
この状態はそもそもディスク障害が疑われるので速やかにファイルの待避をしたいのですが、以下の様な問題が出てきます。
- そもそもバックアップしたいファイルはrootでないとアクセスできない場所にある
- rootログインは許可しておらず、都度
sudo su -
する運用にしていた scp
でファイル転送しようにも、SSHできるユーザー権限でバックアップしたいファイルにアクセスできないchmod
chown
でアクセス許可を変更しようとしても、Read-only file system
のエラーが出て変更できない- ファイルシステムがRead-Onlyなので、新規のauthorized_keysなどの追加もできない
- \(^o^)/
なかなか参りましたね。こういった状況でどうやって問題をくぐり抜けるのか、腕の見せ所さんです。Linux Adminとしての経験と手札の多さが試される。
ramdisk tmpfs(/dev/shm)
を使って解決
いくつかの解決方法が考えられます(後述)が、ここではできるだけ他の環境に手を入れない方法を検討してみた所、 /dev/shm
にramdiskがマウントされていることに気づきました。
# df -h
Filesystem Size Used Avail Use% Mounted on
udev 208M 0 208M 0% /dev
tmpfs 49M 1.4M 47M 3% /run
/dev/sda2 20G 19G 0 100% /
tmpfs 241M 88K 241M 1% /dev/shm
(略)
mount
コマンドの出力結果を確認しても、tmpfsは rw
(Read-Write)であることが分かります。
$ mount
(略)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
(略)
というわけで、ここを一次作業領域として使えばよさそうですね。
ちなみに、/tmp
をramdiskとしてマウントしているdistributionもあるようですが、Ubuntu系などは /tmp
は /
とは分かれてパーティショニングされていませんでした。なので、この場合 /tmp
はRead-Onlyになっていて使えません。
ファイルをサルベージする
ここではramdiskの領域が241MBほどあり、バックアップしたいファイル群もそのサイズ以下だったので、
# tar zcf /opt/backup/files /dev/shm/backup-files.tgz
でバックアップし、そのファイルのpermissionをSSHユーザーでアクセスできるようにした上でscp
することで解決しました。
バックアップしたいファイルサイズがramdisk以下の場合であれば、これがお手軽そうです。
他に考えられる方法は?
その他に考えられる方法を検討してみます。実際にできるかどうかまでは確認していませんが、手段の案として。
- ramdisk上にディレクトリを作り、
/root/.ssh
をマウントする。ramdiskに置かれた.ssh/authorized_keys
を編集すればrootとしてscp
できるはず nc
などの標準入出力をやり取りできるプログラムを通じて無理矢理転送する(tar -
を使うと標準出力にtar
のアウトプットを出せる)- SSHした先で
sudo
を含むtar -
で標準出力にデータ出力スクリプトを実行し、手元で受け取るssh hoge@example.com 'sudo tar zcf /opt/backup/files - |'tar zxf -
みたいな?試してませんがこんな感じでやれるはず
aws-cli
が入っている環境であれば、s3 sync
などを使ってバックアップ(gcloud
などでも可、接続用の情報が環境変数から渡せる必要がある)
その他にも、色々追い込まれればなんとかする方法は思いつけそう
まとめ
たまたま扱ってた環境が今回の状況にハマったので試行錯誤してみました。
こういう普通じゃない状況に陥ったときにはLinuxベース力と経験が試されますね。精神衛生には良くないですが、たまにであれば頭の体操に良いかもしれません。ではでは。