2014年6月22日 星期日

Drupal 搬家/升級/還原筆記

自從幾個 drupal 網站在我手上燒毀之後, 再也不敢怠慢輕忽。 其實 Drupal 已有一個 Backup and Migrate 模組, 可以在網頁管理介面下操作, 也可以自動定時備份。 但貴哥需要看到命令列才有安全感。 所以重生後的網站, 我用 cron 每週一大備份、 每天一小備份, 並且每天把備份檔 rsync 到遠方其他機器上面。

但是真的遇到狀況時, 要如何還原呢? 還原的時候, 既然整個站需要砍掉重練, 那麼可否順便一起升級 drupal 核心呢? 甚至環境從 fedora 變成 debian, 根本就是大搬家, 可行嗎? 本文分享 drupal 7 還原資料庫順便升級/搬家的經驗。

強列建議: 在進行本文的任何一個實驗之前, 請事先至少準備一份完整備份, (第二節的 drush archive-dump ...) 不然網站毀了你就哭了。 此外, 最好另開一部虛擬機或救命碟來做實驗。

以下絕大多數的 drush 指令都必須在你的 drupal 根目錄底下執行, 也就是要先下 cd /var/www/drupal7 之類的指令。

[2015/4/17 補文及修改]

一、 準備工作

首先讓舊家進入維修模式。 第一種方式是進入內建的維修模式: drush vset maintenance_mode 1 但這樣訪客就只能看到維修訊息。 我個人偏好使用 read only mode, 這樣訪客還是可以查資料, 只是任何人都無法張貼文章或留言而已。 這樣 (行將作廢的) 舊資料庫就不會再繼續變動, 搬家這段時間才不會出現「增刪修改全在做白功」的現象。

超級重要! 請先用第三節「完整備份與還原」的 drush archive-dump ... 指令完整備份出舊網站。 萬一遺漏以下任何一項, 都還可以從這裡面挖出來。

退而求其次, 若有備份以下資料, 或許也可以手動拼湊還原網站:

  1. 先前在舊家裡面用 drush pm-list --pipe 所印出來的 「已安裝模組清單」。 或是 ls sites/all/{modules,themes} 的結果也有類似效果。
  2. 先前在舊家裡面用 drush sql-dump 所備份出來的資料庫。 (詳見第二節 「資料庫備份與還原」)
  3. sites/default/files/ 整個資料夾。 這裡存放著所有使用者上傳的檔案。

如果是原機還原的話, 也把 /etc/drupal/7/sites/default/dbconfig.php 備份出來, 裡面有資料庫的帳密。

二、 資料庫備份與還原

這個指令會把整個 drupal 資料庫印到螢幕上: drush sql-dump 所以可以這樣存檔: drush sql-dump | gzip > drupal-sql-dump-150417.gz

又, 查詢日期的 date 指令可以這樣下: date '+%y%m%d' 所以如果想要把備份指令寫入 cron, 並且將每天的備份依日期命名, 那麼可以這樣寫: drush sql-dump | gzip > drupal-sql-dump-$(date '+%y%m%d').gz 這就是我所說的每日小備份。

[重要! 請先做下一節的完整備份, 再回頭來做這一節的還原實驗] 要還原資料庫, 可以這樣下: gunzip < ~/drupal-sql-dump-150417.gz | drush sql-cli 詳見 這篇問答

但是資料庫備份還原並不包含上傳的檔案。 所以如果用這個方式搬家, 在新家會看不見先前上傳的檔案 (包含圖片)!

[2015/12/25] 後來我已不做每天的資料庫備份, 而是改成每天循環完整備份:

BACKUP_PATH=$BACKUP_DIR/drupal7/ard-daily-$(date '+%w').tgz
cd /var/www/d7
drush archive-dump --destination=$BACKUP_PATH --overwrite

這樣永遠會保留最近七天的備份, 星期天備的叫做 ard-daily-0.tgz、 星期一備的叫做 ard-daily-1.tgz 等等。

三、 完整備份與還原

這個指令會把 drupal 程式碼、 資料庫、 上傳檔案全部都備份起來: drush archive-dump --destination=/abc/xyz/drupal-backup-150417.tgz 這就是我所說的 (每週) 「大備份」。

還原之前, 要先把原先的 drupal 根目錄清空, 例如 rm -rf /var/www/my_drupal 當然, 以下的 drush 指令在任何地方都可以下, 因為現在已經無家可歸了 (沒有 drupal 根目錄可去)。 指令如下: drush archive-restore /abc/xyz/drupal-backup-150417.tgz --destination=/var/www/my_drupal --db-url=mysql://root:'(新家)資料庫管理大大密碼'@localhost/drupal7 注意: localhost 請照抄, 不要改成你的 ip, 因為一般預設 mysql 只提供服務給本機 (localhost) 的程式 (例如 drupal); 如果把它改成 ip 位址反而會出錯。 最後面的 drupal7 是任選的資料庫名稱。 如果是本機還原, 資料庫那段的 username (root) 跟 password 就改成先前 /etc/drupal/7/sites/default/dbconfig.php 讀出來的值。

如果單純只是要備份/還原/搬家, 沒有要升級, 那麼用 drush archive-dump 就夠了。 詳見 drush archive-restore

四、 原地升級

註: 寫完這篇之後才發現: 如果你只是想升級, 並沒有要還原/搬家, 那麼根據 「用 drush 升級」 這篇, 理想狀況下只需要 drush up 一個指令就完成。 下完指令後後再回到本文, 直接跳到第九節 「檢查報告」。

* * * * 以下是比較複雜的狀況: 手動分解動作升級並搬家。* * * *

五、 安裝 drupal 核心

安裝一個可登入、 有簡潔網址的 (幾乎全空) drupal。 例如按照 我為 debian 所寫的 drupal 7 講義 做到第三節 「初體驗 & 簡潔網址」 結束為止。 站名/密碼隨便亂設沒關係, 反正等一下還原資料庫的時候馬上會被正確的值蓋掉。

六、 還原所有使用者上傳的檔案

  1. 把新家裡面的 sites/ 備份出去。 最重要的是新版設定檔 sites/default/settings.php 。
  2. 把新家的 sites/ 整個刪掉, 再把舊家的 sites/ 整個資料夾複製過來。
  3. 把剛剛備份的新版設定檔 sites/default/settings.php 重貼回去。
  4. 記得把檔案所有權人改一下: chown -R www-data:www-data sites/default/files

七、 重裝所有外掛模組

假設先前你在舊家曾經這麼下: drush pm-list --pipe | sort > ~/pm-target.txt 現在你在新家再度這麼下: drush pm-list --pipe | sort > ~/pm-empty.txt 於是可以找出兩者的差異, 產生 「待安裝模組清單」: comm -1 -3 ~/pm-empty.txt ~/pm-target.txt > ~/pm-to-install.txt

然後你可以這樣把舊家的所有模組一口氣全部安裝到位: for m in $(cat ~/pm-to-install.txt) ; do drush dl $m ; done 其中會出現很多警告與錯誤訊息, 主要是因為某些模組其實並不獨立存在, 而是附屬於其他模組之下。 反正安裝主要模組的時候, 這些從屬模組會自動被安裝進來。 所以這沒關係, 直接忽略就好。 安裝完畢之後, 可以再比較一次: drush pm-list --pipe | sort | comm -3 - ~/pm-target.txt 如果還是有些許差異, 可能是因為某些模組升級之後, 其中的從屬模組改名字或增刪過了吧, 我也不清楚 :-)

八、 還原資料庫

比方說先前在舊家用 drush sql-dump 備份起來的資料庫放在 ~/140621.sql.gz 好了。 那麼可以這樣還原資料庫: gunzip < ~/140621.sql.gz | drush sql-cli 這樣, 包含使用者、 文章、 ... 等等各種資訊就全部還原了!

有可能需要下: drush vset maintenance_mode 0 結束維修模式, 重新上線。 如果一切順利的話, 現在你的新家看起來應該跟舊家差不多了。 不過我沒那麼順利...

八之一、 插曲

一般正常情況下是不需要這一小節的。 我從 7.22 升級到 7.28 時, 遇到一些狀況。 根據第一次的錯誤訊息搜尋到 這篇, 結論就是這當中正好遇到 drupal 的一個 bug。 只需要下這兩個指令就可修復:

    drush dl rules
    drush updatedb

但我照著做又遇到錯誤, 再用第二的錯誤訊息搜尋到 這篇。 原來是我的 data_... 相關模組未啟用。 於是: 處理方式是:

    drush pm-list | grep data
    # 記下哪些已啟用、 哪些未啟用
    drush pm-enable data data_ui data_entity data_search
    drush updatedb
    drush pm-disable data data_ui data_entity data_search

總之, 錯誤訊息 就是你最好的朋友 可以讓你 google 到跟你有相同遭遇的好朋友。

九、 檢查報告

外觀正常還不夠。 請以 admin 身份登入, 點選 「報告」=>「狀態報告」。 應該會看到很多紅色的錯誤訊息。 以我所看到的為例, 包含了:

  1. site/default/files/private/.htaccess 等等幾個檔案的設定不安全。 點到它所建議的連結, 拉到很下面有一段 「For drupal 7」 的設定碼, 把它貼到 .htaccess 取代原本的設定就 OK 了。
  2. CKEditor、 Superfish、 jQuery Cycle 等等好幾個模組的 javascript 碼不見了。 這些都很好處理, 就是要像當初安裝時一樣, 到各自的官網把最新版的 javascript 碼抓回來放到正確的位置就可以了。

基本上大部分的紅色報告都會給你一些建議, 照做就是了。 但有一個跟資料庫相關的紅色報告比較麻煩, 下一節詳述。

十、 資料庫重整

紅色報告當中可能出現的較棘手項目是 「資料庫 schema inconsistent」。 即使下 drush updatedb 指令, 它也只是告訴你 「資料庫不需更新」, 但錯誤可能依舊存在。 點進去查看 (或是從 「架構」=>「schema」 進入), 看見報表當中可能出現四個項目:

  1. 「Match」 (「匹配」): 謝天謝地, 這是 OK 的部分。
  2. 「Extra」: 這是多出來的部分。 像我的舊家有安裝 ubercart 模組; 但在新家當中省略不安裝, 所以這些舊的資料表其實可以刪掉了。 其實不刪也沒關係啦, 只是礙眼一點、 浪費一些空間而已。 但是對於一位 drush 命令列及 regexp 愛用者而言, 讀過 這篇 之後馬上會想到: 刪除幾十個表格其實也不過就是個舉手之勞而已。 先下這個指令: drush schema-compare extra | perl -pe 's/\n/,/' | perl -pe 's/(.*),$/drop table $1;/' > drop-extra-tables.sql 並檢查新產生的文字檔 drop-extra-tables.sql 的內容, 確認一下: 每一個多出來的表格真的都可以刪除嗎? 然後 drush sql-cli < drop-extra-tables.sql 把它們全部燒毀! 重新整理網頁, 看到 「Extra」 變成 0 了。 怎麼樣, 現在還有人要用滑鼠選單跟我的鍵盤比賽嗎 :-)
  3. 「Mismatch」: 這代表資料庫的內容跟宣告的格式有一些不一致。 這個狀況最難處理。 不過, 根據 這則留言 的說法, 好像可以直接擺爛放著不要處理也沒關係。
  4. 「Missing」: 這代表某些表格不見了。 不應該有這種狀況的。 如果遇到了, 那就哭吧。 還有別的資料庫備份嗎? 沒有的話我猜就沒救了吧 :-( (別太相信我。 請 google。)

十一、 其他

看得到錯誤訊息的問題都還比較容易搜尋答案; 最難處理的就是看不見錯誤訊息的問題。 像我的 menu_import 模組不能用了 -- 原本在 「架構」 => 「選單」 底下, 應該要有 「import menu」 跟 「expport menu」 這兩個分頁; 但不知為何升級後就看不見了。 (還是很久以前就不見了?) 刪除模組再重裝還是沒用。 必須刪除模組、 刪除 sites/all/modules/menu_import/ 整個子目錄、 再重裝, 然後那兩個分頁就又出現了。

很可能還有其他破破的地方, 只是一時沒看到而已。 以後如果看到再補上來。

十二、 結語

我的這次搬家實驗先是從 fedora 17 搬到 debian 7.1 , 大致成功 (第九節「檢查報告」結束) 就停下來。 然後完整的搬遷其實是在 fedora 17 上面換個目錄重新安裝新的核心及模組而已。 我對這些機器都有完整的 root 控制權, 所以問題還算單純。

如果你所租用的網路虛擬空間開放給你的權限太少, 例如沒有 shell 甚至 .htaccess 開放權限不足, 那麼可能會遇到更多問題。 這一篇 「搬家注意事項清單」 討論更多限制條件下的搬家, 對於 DNS 重設也做了一些提醒。

不論你的搬家/升級條件多麼單純, 看來只要涉及升級核心, 總免不了搬完家之後會遇到一些卡卡的地方。 這則留言 感嘆: 他管了一些舊站, 從 4.5 和 4.6 一路升級上來, 很自然地 「健康狀況」 也就越來越差。 不過我覺得: 一個網站居然能夠從 2004 年左右 (根據 歷史記錄) 的 4.5 一路升級到 2012 年的 7.0 , 這已經很強了吧! 這也讓我更覺得當初選用 drupal 架站是正確的決定, 並且不再害怕未來可能面臨的 Drupal 8 升級。 我也很好奇: 如果不是用自由軟體所架的網站, 一般能夠享受多久的程式碼持續升級維護呢?

沒有留言:

張貼留言