天天看點

記一次FreeBSD的冒險更新修複之旅

一台伺服器使用FB 10.4已經很長時間了,因為Let’s Encrypt從2019年12月1日開始,ACME v2啟用,要求certbot最低版本是0.29.0,

而10.4最高隻支援到0.27.1,頭腦一發熱,就準備更新到11.0,

freebsd-update -r 11.0-RELEASE upgrade

freebsd-update install

shutdown -r now

pkg-static install -f pkg

pkg update

pkg upgrade -f

...

這麼一套組合拳下來,花了好幾個小時後,更新完成了.

可是....mysql沒有啟動.

檢視log,發現有如下錯誤:/usr/local/libexec/mysqld: Undefined symbol "fdatasync"

搜尋一通,說是更新到FB 11.1可以解決,那麼就繼續折騰吧.

可是,這次就報錯了: freebsd-update gunzip: (stdin): unexpected end of file

又是一通折騰,最後看到說應該是之前的更新沒有弄好,應該freebsd-update rollback,我腦子一抽,居然就執行了這個指令.

看着螢幕上顯示删除了xxx,心裡就覺得不妙,但此時已經沒法中斷了.

硬着頭皮重新開機後,ssh卻連不上了.心情降到了冰點.深呼吸,喝了口茶定定神,想到雲伺服器還可以vnc的方式登入,死馬當活馬醫,萬幸萬幸,連上并登入上去了.

但是,執行freebsd-update -r 11.0-RELEASE upgrade還是報gunzip: (stdin): unexpected end of file,并且提示卻缺少一些lib,之前的sshd沒有啟動,也是提示缺少了一些lib.

走投無路了,這時候,好運氣終于開始來了,峰回路轉了,我搜到了這個文章:

https://mpc.lists.freebsd.questions.narkive.com/sUJyHY80/problems-with-upgrade

同是天涯淪落人啊,10.3R -> 11.1R -> rollback -> 10.4,哈哈哈哈

回帖的真是高手,膜拜膜拜.

立即開始着手找10.4版的base.txz,國内所有的鏡像,最低都是11.2了,最後,在官網上找到了連結.可是,現在ssh已經不能用了,下載下傳了這個怎麼傳到伺服器上呢? 愁啊

哎,淩晨兩點了,腦子不好使啊,為了怎麼上傳base.txz,居然想了半個多小時.最後,還是想到了直接在伺服器上:

fetch

http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/amd64/10.4-RELEASE/base.txz 接下來,就是完全按照文章來了:

cp base.txz /tmp/
xz -dc base.txz|tar tvf - | egrep 'libldns.so.5|libheimipcc.so.11'
# 或者
xz -dc base.txz|tar tvf - | egrep 'libldns.so.5|libheimipcc.so.11' | egrep -v '^l'
# 确定丢失的lib确實是base.txz包含的.
# 然後
xz -dc base.txz|tar xvf - ./usr/lib/private/libldns.so.5 ./usr/lib/private/libheimipcc.so.11
# 可以看到/tmp/usr/lib/private/下已經解壓出了這兩個lib
# 因為我的/usr/lib/private下完全沒有這兩個lib檔案,是以備份就省了
cp /tmp/usr/lib/private/libldns.so.5 /usr/lib/private/
cp /tmp/usr/lib/private/libheimipcc.so.11 /usr/lib/private/           

然後

service sshd start

沒有報錯了,用netstat -anp tcp看看,tcp/22端口已經正常監聽.用ssh也沒有問題了.

因為nginx和mysql還是提示有問題,缺少libssl.so.8這個檔案. 然而在base.txz裡沒有這個lib

事後想來,應該是之前的更新,把nginx和mysql都已經更新到11.0這個版本下的package,是以依賴應該也是11.0這個版本的裡.

我想重裝這個nginx,可是pkg卻提示有問題,一通搜尋折騰後,用以下方法解決了pkg的問題:

pkg-static update
pkg-static del -f pkg
pkg
# 根據提示安裝pkg           

先備份了nginx的配置檔案,然後:

pkg upgrade -f nginx           

nginx和相關的依賴都被降級了,nginx也沒有問題了.

mysql還是不能用,不管了,先冷備份資料目錄和配置檔案吧.猶豫再三,還是敲下了

pkg upgrade -f mysql57-server           

滿懷希望的敲下service mysql-server start,然後netstat -anp tcp,可是,tcp/3306端口沒有開

what?? 檢視log,還是提示缺少libssl.so.8

這不科學啊,pkg info|grep mysql,版本沒有變化,也就是說,pkg upgrade -f mysql57-server沒有效果.

思來想去,還是先修複client吧:

pkg upgrade -f mysql57-client           

這回的終端輸出,提示了client正确降級,并且相關的依賴也降級了.

該來的還是要來了,一咬牙一閉眼,顫抖的手敲下了:

pkg del -f mysql57-server
# 嗯,隻删除了這個包,沒有其它依賴被删除
pkg install mysql57-server           

檢查了配置檔案和資料檔案沒有被修改後,敲下service mysql-server start,然後netstat -anp tcp,哦也,成功了.

至此,伺服器終于恢複了正常,沒有耽誤使用.

反思&教訓:

  1. 生産伺服器除非必要,盡量不要更新,尤其是跨大版本更新;
  2. 更新後,千萬千萬不要做rollback,尤其是跨大版本更新;
  3. 更新之前,一定要做備份,雲伺服器做快照是一個很友善的方式

因為使用freebsd-update -r更新耗時太久,是以生産伺服器的更新方案(設想未經驗證):

  1. 在同區同機房短期購買一台同等配置的雲伺服器(或許可以差一些),比如按量購買,或者購買一個月;
  2. 使用最新的鏡像初始化伺服器,然後更新到最新版本的系統和軟體;
  3. 建立一個快照或者鏡像.
  4. 将生産伺服器上的應用與資料,備份/遷移到新的伺服器,測試是否正常.資料遷移可以走内網.
  5. 如果一切正常,那麼對于新的伺服器,做一個自定義鏡像.
  6. 對于原來的生産伺服器做一個快照備份.
  7. 對于原來的生産伺服器,使用自定義鏡像初始化.
  8. 測試生産環境,正常就可以上線了.如果有問題,就恢複之前備份的快照.

繼續閱讀