記一次誤操作刪除800G數據的經歷
前因後果
2021年2月5日,我正在嘗試運行一份示例代碼。該腳本類似這樣:
# 这里有检查$REC_ROOT,但本脚本内并未处理,所以只会输出缺少环境变量$REC_ROOT,但继续执行
./config.sh
if [ ! -d $WAV_ROOT ]; then
echo "Cannot find wav directory $WAV_ROOT"
exit 1
fi
data="$REC_ROOT/data"
# 其他代码
if [ $stage -le 0 ]; then
echo ""
echo "Stage 0: Preparing data"
rm -rf $data/*
local/chime1_prepare_data.sh || exit 1
fi
由於腳本來自知名開源項目,我並沒有仔細審查。另外由於對相關代碼並不熟悉,我也沒有正確配置相關環境變量,所以腳本中的WAV_ROOT和REC_ROOT理所當然是未定義的。
我就這麼冒失地執行了腳本,而它在打印兩句警告後並沒有停止執行,所以我認為環境變量並不是必須的,於是放任它繼續執行。由於該腳本執行的是耗時任務,我將控制臺隱藏到後臺,去完成其他任務。
過了十幾分鍾,我收到一個應用程序的崩潰報告,因為相關文件不存在。我疑惑地檢查,發現數百GB的數據已經不翼而飛。此時我才想起那個正在執行的腳本,切換過去後發現它還沒有停止執行,正在瘋狂刪除我的文件。我趕忙殺掉了腳本,但包括由於沒有root權限而刪除失敗的,原本800GB+的數據只剩5.6G。
讓我們來看看發生了什麼。
首先,腳本調用config.sh,檢測到REC_ROOT環境變量不存在並打印警告。
然後腳本繼續執行,if [ ! -d $WAV_ROOT ]; then這裡是在檢測WAV_ROOT是否是一個目錄,如果不是,就退出腳本。按理說我並沒有配置任何環境變量,此處應該退出。但bash腳本神奇地,當WAV_ROOT為空或者不存在時,這個檢測會認為這是一個目錄,從而通過檢測。即:
unset NOT_EXIST
if [ -d $NOT_EXIST ]; then
echo "this is a directory"
fi
上面的腳本是會輸出的。
或許是因為參數為空時bash默認檢測當前目錄,以至於目錄檢測總是通過。
再然後,由於REC_ROOT未定義,$data=/data,然後相當於:
rm -rf /data/*
非常不巧和不幸的是,我將一塊1TB的數據盤掛載在了/data上,於是迎來了降維打擊。該數據盤中有800G+的數據,文件量大於10萬,因此非常耐刪,過了十幾分鍾還給我剩了幾個G。而大量讀寫操作將數據恢復的難度推到了地獄級。
搶救措施
在殺掉腳本之後,我嘗試卸載數據盤,但卸載失敗,提示正忙。情急之下我忘記了可以通過正在運行的進程恢復它們打開的文件,而是想到先關機避免更多的讀寫。關機前發現VSCodium還在運行並且有未關閉的文件,於是搶救出幾個正在編輯的代碼文件。而這成了本次事故中我唯一搶救成功的文件。
之後,通過U盤刻錄的系統修改原系統的配置,取消掉自動掛載數據盤,然後系統啟動後以只讀方式掛載數據盤嘗試恢復數據。
正如前面所說,大量的讀寫操作讓我失去了恢復的機會,嘗試了不少恢復工具,但都沒法掃描出目錄結構,唯一可能有效的方法是通過特殊的文件頭結構進行特徵掃描,但這只能恢復一些特殊格式的文件,而對我最重要的都是純文本數據,至於一些視頻文件,由於尺寸太大數據分散在不同的塊,也是基本沒戲的。
還好,雲端備份讓我不至於一無所有,但還是痛失最近一個月的活動數據和大量不可描述之物。
總結
數據無價,謹慎操作。備份得當,也別太浪。