とあるEC2上のサーバーにて、サーバー内にあるバックアップファイルをS3に転送するバッチを作成していたんですが、そのテスト中に急にコマンドが叩けなくなってしまう現象が発生しました。
なんだ?と思って、サーバーに再度SSH接続しようとしたところ、SSH接続もできなくなってました。
(ここでサーバー抜けるなよという話ではありますが。。。)
バックアップデータはEC2の中だし、詰んだ。。。
と思ったのですが、なんとか復旧できたので備忘録として残しておきます。
何をやらかしたのか
EC2からS3へのファイル転送する際に一旦/tmp/backups
ディレクトリにバックアップファイルを移動する処理にてバグがありました。
詳細は避けますが、以下のようなイメージです。
# 一時的にバックアップファイルを置く場所
TMP_DIR=/tmp/backups
# 前回の一時ファイルを削除
sudo rm $DIR/*
# 一時ディレクトリにコピー
sudo cp -a /data/xxxxx/backups/* $TMP_DIR/
rmコマンドの引数で$TMP_DIR
を$DIR
と存在しない変数を参照していました。。。
これにより、本来rm /tmp/backups/*
となるべき処理でrm /*
となってしまいました。
何が起きたか
というわけで、ルートディレクトリ直下にあるファイルが全て消えました。。。
(-rf
オプション指定してなかったから最悪の事態にはならなかった)
ただ、普通のLinuxであればルート直下ってディレクトリしかないから問題ないはずじゃ?って思ったんですが、AmazonLinux2だとbin
ディレクトリなどがシンボリックリンクとなっていることが分かりました。。。
↓正常なAmazonLinux2インスタンスでルートディレクトリを出力した場合
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ ll -a /
total 4194320
dr-xr-xr-x 18 root root 273 Aug 18 03:03 .
dr-xr-xr-x 18 root root 273 Aug 18 03:03 ..
-rw-r--r-- 1 root root 0 Oct 10 2019 .autorelabel
lrwxrwxrwx 1 root root 7 Aug 18 03:03 bin -> usr/bin ⇒ 消えた
dr-xr-xr-x 4 root root 4096 Oct 10 2019 boot
drwxr-xr-x 14 root root 2860 Aug 18 03:08 dev
drwxr-xr-x 82 root root 8192 Sep 15 2020 etc
drwxr-xr-x 3 root root 22 Oct 10 2019 home
lrwxrwxrwx 1 root root 7 Aug 18 03:03 lib -> usr/lib ⇒ 消えた
lrwxrwxrwx 1 root root 9 Aug 18 03:03 lib64 -> usr/lib64 ⇒ 消えた
drwxr-xr-x 2 root root 6 Aug 29 2019 local
drwxr-xr-x 2 root root 6 Apr 9 2019 media
drwxr-xr-x 2 root root 6 Apr 9 2019 mnt
drwxr-xr-x 4 root root 27 Aug 29 2019 opt
dr-xr-xr-x 201 root root 0 Aug 18 03:08 proc
dr-xr-x--- 3 root root 140 May 25 2020 root
drwxr-xr-x 28 root root 1060 Aug 18 03:08 run
lrwxrwxrwx 1 root root 8 Aug 18 03:03 sbin -> usr/sbin ⇒ 消えた
drwxr-xr-x 4 root root 41 Aug 5 2020 srv
-rw------- 1 root root 4294967296 Sep 15 2020 swapfile
dr-xr-xr-x 13 root root 0 Aug 18 03:13 sys
drwxrwxrwt 10 root root 266 Aug 18 03:31 tmp
drwxr-xr-x 13 root root 155 Aug 29 2019 usr
drwxr-xr-x 19 root root 269 Oct 10 2019 var
binとかlibへのパスが通らなくなったのでコマンドが使えなくなったようです。。
復元方法
以下の記事を参考に復元することが出来ました!ありがたやT^T
【簡単な手順】
- 問題のEC2インスタンスを停止(終了させるとEBS消えるので絶対やらないこと!!!)
- ストレージタブにてルートデバイスのパスをメモ(
/dev/xvda
とか)
- ストレージタブにてルートデバイスのパスをメモ(
- 問題のEC2インスタンスからボリュームをデタッチ
- 復旧用に新規でEC2インスタンスを作成(microインスタンスでボリュームも最小限で良い)
- ネットワーク設定でアベイラビリティゾーンを上記ボリュームと同じにする必要あり
- 問題のボリュームをアタッチ
- ルートデバイスはデフォルト(
/dev/sdf
)で良い
- ルートデバイスはデフォルト(
- 復旧用EC2にSSH接続
- 問題のボリュームをマウントする
# アタッチしたボリュームの確認
ll /dev/ | grep sdf
lsblk
# マウント
sudo mkdir /mnt/vol01
sudo mount /dev/xvdf1 /mnt/vol01
- シンボリックシンクの作成
cd /mnt/vol01
sudo ln -s usr/bin bin
sudo ln -s usr/lib lib
sudo ln -s usr/lib64 lib64
sudo ln -s usr/sbin sbin
- 復旧用EC2を停止
- 問題のボリュームをデタッチ
- 問題のボリュームを元のEC2インスタンスにアタッチ
- 最初にメモっておいたルートデバイスを指定(
/dev/xvda
とか)
- 最初にメモっておいたルートデバイスを指定(
- 問題のEC2インスタンスを起動
これで、無事にSSH接続して元の状態に戻ったことが確認できました!!!
教訓
rm
コマンドは気を付けましょう!
無事に復元できてよかったですが、まじで血の気が引きました。。。