Linux系統診斷小技巧(13):啟停問題之如何修復grub損壞
grub損壞,是導致系統啟動失敗比較常見的原因。如何解決這類問題呢?
解決問題,好用的工具很重要。我們先討論下好用的工具。
三大利器
關於工具的重要性我們就不絮叨了。解決啟停問題,一定要有三大利器的輔助
- 快照
- VNC
- 錄屏工具
快照
快照對排查啟停問題,有三個方面的用處。一是保留現場。有了這個現場,不管我們排查中做了什麼變更,我們總是能夠回撤到現場。這是現實版後悔藥。二是在沒有辦法進入系統的情況下,快照可以讓我們把問題磁碟掛載到其他例項上。這樣我們有了一個排查、診斷和修復的途徑。三是快照提供了多種可選擇的途徑讓我們可以使用修復後的資料和結構。比如新建磁碟掛載拷貝、製作安裝映象覆蓋有問題的系統盤等等。

VNC
高速公路是有應急車道的。同樣我們的業務系統也需要應急車道,用以解決異常、緊急等非常規問題。VNC就是我們的應急車道。
當然,VNC不是唯一可用的方案。這裡的關鍵是在系統異常時,提供一個root shell供排查只用就好。
錄屏工具
各主流平臺都有好用的錄屏工具,功能大同小異,大家使用順手即可。為什麼我們要建議大家都配備錄屏工具呢?
系統啟停時,Linux控制檯上的系統輸出很快。有些關鍵的報錯資訊,你可能完全沒有機會看到就過去了。如果類似資訊完全沒有記錄到日誌中。那麼,你可能被後面的日誌給誤導。
題外話:bind掛載
修復啟停時經常需要做 chroot 操作,即我們要在一個新的根檔案系統內操作。但是,只執行 chroot 是不夠的。我們還需要掛載 /dev 、 /proc 和 /sys 目錄。
但是,因為 /dev 、 /proc 和 /sys 不是裝置,直接掛載是不可行的。這裡的技巧是使用 ofollow,noindex" target="_blank"> bind 掛載方式。
mount --bind /olddir /newdir # bind掛載選項例項 for d in dev proc sys;do mount /$d /new_root_dir/$d;done # 切換根檔案執行chroot前,先掛載需要的系統目錄
回到話題
如何復現現場?
我們通過覆蓋磁碟第一扇區來破壞grub的引導程式碼部分,觀察下grub被破壞後,例項啟動的情況

具體操作的命令如下。注意,危險操作,切勿隨意模仿。
fdisk -l -u /dev/{xvda,vda} # 確定系統盤裝置路徑 dd if=path_to_sys_disk bs=448 count=1 2>/dev/null | od -tx1 # 檢視MBR內容 dd if=/dev/zero bs=448 count=1 of=path_to_sys_disk # 覆蓋MBR dd if=path_to_sys_disk bs=448 count=1 2>/dev/null | od -tx1 # 驗證已經覆蓋了MBR reboot # 重啟
執行過程如下( fdisk 操作沒有顯示)
修復
那麼,怎麼修復呢?grub損壞的修復方法簡潔明瞭:重新安裝grub即可。但是當前例項啟動失敗了,無法對問題系統進行讀寫處理。
所以我們需要解決的問題是兩個:
- 通過什麼方式來處理系統盤。
- 怎麼重新安裝grub。
解決第一個問題的方法很多。這裡我們給大家推薦能夠使用快照的方法。這個方法雖然稍顯囉嗦,但是卻能讓我們全程掌控。
如何使用快照?
我們為問題例項的系統盤做快照。然後再從快照新建磁碟。新建磁碟和系統盤內容一樣,但是可以作為資料盤掛載到正常例項上。
這樣我們就可以在正常例項上對新建立的磁碟做處理。調整配置、適當修改,而後重新安裝grub。
整個思路圖示如下

具體操作示例如下
首先做快照

給快照個顯著的名字

良好規劃和維護的系統盤,一般都尺寸不大

現在新建磁碟
處理系統盤的問題解決了。那麼,怎麼重新安裝grub呢?
重灌grub
主流Linux發行版都提供了 grub-install 工具(名稱也可能是 grub2-install ),大家直接呼叫即可。但是有幾點大家要注意。
小提示
首先,grub的引導器預設使用 IOS" rel="nofollow,noindex" target="_blank">BIOS 的 磁碟命名慣例 ,這與Linux是不同。所以grub提供了配置檔案,用來在BIOS的磁碟命名和Linux系統的磁碟命名之間轉換。
這些配置檔案如下:
版本 | 應用配置 | 系統配置 |
---|---|---|
grub | /boot/grub/device.map | /etc/{sysconfig,default}/grub |
grub2 | /boot/grub2/device.map | /etc/{sysconfig,default}/grub |
如果是KVM例項,則磁碟是vda;如果是較老的XEN例項,則磁碟是xvda。
第二, grub-install 的操作物件是磁碟還是分割槽。不要給錯引數。
第三,如果您的系統比較老。那麼,您可能會碰到已知bug: grub-install工具不能處理/dev/xvda*路徑 。
重灌步驟
有了以上的鋪墊,我們給出重新安裝grub的步驟
- 把新建磁碟掛載到正常例項上,以便對之讀寫、修改。
- 掛載目標根檔案系統,我們需要改動grub的 device.map 檔案。
- 把/dev、/proc和/sys掛載到新掛載檔案系統。這樣我們就能夠使用核心匯出的系統資料了。
- chroot到目標根檔案系統,使之成為當前跟檔案系統。
- 檢查和核實/boot/{grub,grub2}/device.map和/etc/{sysconfig,default}/grub配置檔案中磁碟名稱是否正確。
- 使用 grub-install 來重新安裝grub。
這些步驟,用指令碼來表達,如下
# 1. 掛載新建磁碟到正常例項需要在控制檯操作 # 2. 把新建磁碟在例項內部掛載上。這裡我們假設/dev/vdb是系統盤 mount /dev/vdb1 /mnt # 3. 通過bind方式,掛載系統目錄到新根檔案系統 for d in dev proc sys;do mount --bind /$d /mnt/$d;done # 4. 切換到新根檔案系統 chroot /mnt # 5. 檢查/boot/grub/device.map或者/boot/grub2/device.map檔案,確認磁碟名稱不當。如有則修改 cat /boot/{grub,grub2}/device.map # 6. 重新安裝grub。因為是在其他例項上以資料盤的方式,因此是第二塊磁碟。 grub-install /dev/vdb
我們按照上面的步驟,把前面破壞的那臺例項的grub重新安裝下。
首先,掛載磁碟到正常例項
例項內部掛載
接下來我們bind掛載/dev、/proc和/sys
現在切換到新根檔案系統
第五步,檢查磁碟名稱是否需要修改,需要則修改之
最後一步,重新安裝grub
再次請快照出場
怎麼通過修正完畢的新建磁碟來修復問題例項的系統呢?這裡需要注意
- 我們沒有辦法直接使用新建的快照回滾問題例項的系統盤。
- 資料盤的快照不能建立安裝映象。但是,開通了白名單就可以。
我們新建立磁碟是資料盤,其建立的快照是不能回滾問題例項的系統盤的。所以我們只能通過把新建立磁碟轉為系統盤,而後建立安裝映象的方式來恢復問題例項。當然,這需要開通白名單。
即整體思路是這樣的

怎麼把資料盤轉為系統盤?我們會專題討論下。
終焉
祝探索愉快。