跳到網頁內文區。

:::

旅舍更新日誌 卷二


日期: 3.31.’03.

旅人留言本終於重開了~!哦呵呵呵呵呵~! ^_*'

關閉了兩年,留言本終於得以重見天日了。之前的主程式是 1998 年中寫的,距今已經快六年了。原來的程式問題很多,幾年來雖斷續修正一些 bug ,但幾個重大的問題卻遲遲無法突破。為了避免一天到晚在東挖西補,我毅然決定把留言板整個停掉,整個重寫。但因為這些問題都很大,一直無法突破,過了幾個月還是想不出辦法,就整個擱置下來了。就這樣,一擱就擱了兩年。

最近這幾個月來,我的另一個 PHP 網站計劃— Monica —逐漸有了成果,並突破了幾個重大的難關。正好上星期阿光要問我 Linux 的問題,在 ICQ 上找不到我,在 ICQ 上留話,催我快弄一個留言板出來,以便我不在也能留言問我。我想到,何不把 Monica 所累積的經驗,轉移過來呢?把 PHP 的 Monica ,移植到 CGI/Perl 或 mod_perl 環境中,會有什麼結果?我也很想考考自己,以我現在的能力,寫一個留言板,要花多久時間?這就是 Selima 計劃,也就是大家看到的,新的旅人留言板了。移植的工作,花了一個星期左右。 PHPCGI/Perl 或 mod_perl 差別不小,移植的過程多少有點阻礙,但現在看起來,應該算是成功了。 ^_*'

Monica/Selima 所解決的問題,正好也是舊的旅人留言板的主要問題。新的旅人留言板,改善了下列功能:

  1. 留言不再用 <pre>…</pre> 顯示,用一個 a2html() 函式,將留言轉為 HTML ,在保留原留言格式外,也解決了斷行的問題。
  2. 加上語言切換的功能,將原有的中英對照分開,改分成繁簡中文和英文三個語言切換。
  3. UTF-8 存留言,並加上萬國碼處理能力,以解決外地來的朋友,留言會變亂碼的問題。
  4. 改用暫存表單轉向,所有的頁面都是用 GET 來顯示,不再在 POST 上顯示頁面,以避免在 POST 中按下重新整理,會造成重覆留言的問題。
  5. 留言的 E-mail 不會再直接顯示,以避免被廣告商的 E-mail 掃描程式掃描,發廣告信,造成留言的人困擾。
  6. 留言分頁原來是以筆數分類,現改以留言的量分類,避免每頁長度多寡不一。
  7. 針對 mod_perl 的特性而寫,並相容於 CGI/Perl 和命令列模式,執行的效率提高,也提高執行的彈性。

其她還有很多,不及列舉。可惜的是,因為 Selima 的架構,用到很多自己寫的函式庫,要把它們一一放到網站上,頗為困難,更別說要讓人看得懂原始碼了。無法建置成開放原始碼的專案,甚憾。

因為留言板資料檔格式改變,暫時還看不到旅人留言本的舊留言。等我整理完,轉完檔後,會再放上來。

Selima這個字,是來自阿拉伯的女生名字,意思是和平peace。時值美伊戰爭,美國不顧聯合國反對,強行入侵伊拉克,造成無數無辜生命的死傷。取Selima這個名字,一方面為哀悼這些無辜的生命,也希望戰爭早點結束,讓和平早日回到阿拉伯世界。


日期: 11.5.’00.

旅舍依瑪經歷不少的改變,在這裏總結一下。

首先,七月中以後,家裏的 ADSL 固接寬頻網路終於接通了,旅舍和女聲也從原本借用益華主機,改搬到家裏的電腦上。搬遷工作比預期簡單,因為兩邊都是 Windows 2000 伺服器,我已經對 Windows 2000 IIS 5.0 很熟悉了,沒什麼改變。唯一的問題是:我的電腦只是 Pentium Ⅱ 233 ,拿來做主要的 Win32 伺服器,跑得很辛苦。

旅舍和女聲搬遷後,我已經沒有顧忌了。八月中辭掉益華的工作,用離職保證金買了新的電腦 Pentium Ⅲ 800 當新的伺服器,作業系統使用 RedHat Linux 6.2 (現在已經昇級到 7.0 )。剛換 Linux 的時候,真的很辛苦,因為和以前熟悉的 Win32 環境差太多了,整個概念完全不一樣。不過換了一個不錯的新工作,公司裏有一整個書架的 Linux 書,像圖書館一樣天天把書借回家。一直到我對 Apache 熟悉以後,才把旅舍和女聲網站搬到新的 Linux 伺服器上。在女聲編輯手記上的日誌記載,這天是 2000 年 9 月 16 日,大約是買了新伺服器後一個月左右。

搬遷到 Linux Apache 最大的改變在於 HTTP 標頭的問題。原本在 IIS 下並不是用 CGI ,而是用 ISAPI PerlIS 來執行程式, PerlIS 無法設定正確的 HTTP 標頭,所以必需手動設定 HTTP 標頭。可是回到 Apache CGI 下,直接送出完整 HTTP 標頭會導致錯誤,所以只得重寫所有的 HTTP 標頭。

接下來的事情,只能用緊鑼密鼓來形容。

9 月 26 日,做出了留言板使用說明,在女聲訂閱頁上加上求助訊息,加上 HTTP 403 Forbidden 自訂錯誤訊息。這些都是很久以前就想寫的說明。留言板說明主要是在斷行的問題上:留言板不會自動斷行。原則上我不打算自動斷行,因為我玩 BBS 的時候,已經習慣了手動斷行的散文詩格式。可是留言板斷行問題仍然是個很頭大的問題。我參考過蕃薯藤、 Kimo 討論區斷行處理方式,還沒有找到一個比較好的解決方法。這是個仍待解決的問題。

女聲訂閱頁加上了女聲編輯的 E-mail ,以便無法訂閱時有路可循。 HTTP 403 是 Forbidden ,用來保護網站管理程式和女聲訂戶資料。

9 月 28 日,做出了 robot.txt 。這是用來告訴外面的搜尋引擎,哪些地方不可以拿去做全文檢索資料庫。這樣可以避免搜尋引擎把網站管理程式等等的東西都拿去建檔了。

10 月 11 日,網站改用 mod_perl 。這是另一個重要的里程碑。因為公司不用 Perl ,所以一直不知道該怎麼用傳說中的 mod_perl 來加強網站程式效率。後來我找到了 mod_perl 和 mod_perl 的安裝、設定說明,重新安裝整個 Apache 伺服器。沒想到 mod_perl 的 HTTP 標頭處理方式又和 Apache CGI 不一樣。為了避免日後同樣的困擾,我捨棄手動設定標頭,改用 CGI::header() 模組來處理 HTTP 標頭。同時我也拿掉自己寫的 time2str() ,改用 HTTP::Date::time2str()

改用 CGI::header() 處理標頭後,解決了另一個問題: mod_perl 無法持續連線。只要使用 CGI::header() ,就能夠啟動 Apache::Registry 內部的 HTTP 標頭解析引擎,處理連線的相關問題。

我開始捨棄過去的做法。過去為了避免載入外部模組浪費系統資源,我儘量自己寫所需要的模組。現在我儘量引用別人寫好的外部模組,以保持系統的相容性。這是很重要的觀念改變,尤其在 Perl 和 UNIX 程式寫作觀念上:合作。 Perl 程式應該是不同人努力合作的成果,而不是一個程式單打獨鬥處理所有的問題。

UNIX 環境也是。不同程式、行程間相互呼叫、配合、傳遞訊息,以得到結果。 Win32 也可以這樣,只是工具太少,而且所耗的系統資源太多。這也違背了 Win32 環境最初的設計目標。

這時候,才真正進入了 UNIX 的世界,一個和 DOS/Win32 完全不同的世界。

另外, mod_perl 會載入所需模組並常駐在 Apache 行程中,會造成模組變數的混淆。我把原來在共用模組設定的變數,如 $ID 、$THIS_FILE ,搬到個別程式裏設定。為了避免不同網站的共用模組,因為常駐時名稱相同而混淆,我也更改了共用模組的名稱。

我寫了一個有點複雜的算式計算留言本每一冊的最後更新日期。這個算式後來還是改掉了,以避免瀏覽器快取的時間計算混亂。

我下載了 W3CHTML 認證程式網站,開一個虛擬主機來執行。

同一個晚上,我用 gethostbyname() 寫出比較有效的計數器網域判別準則。我也小小修改了前面所提,留言本最後更新日期的算式,以解決沒有留言時無法計算最後更新日期的錯誤。另外,留言存檔後的自訂 HTTP 303 See Other 重新導向訊息,因為 mod_perl 會自行追加 HTTP 303 訊息,導致訊息長度錯亂,使瀏覽器無法判斷訊息長度。我暫時拿掉訊息長度 HTTP Content-Length 標頭,以解決問題。

10 月 19 日,我在每個檔案開檔時加上了 flock() 檔案鎖定,以避免檔案同時讀寫錯亂。這是很久以前就該做的,可是因為一直不清楚 flock() 檔案鎖定的做法,所以沒加上去。這兩天仔細讀了 flock() 的相關說明,覺得很有效,就加上去了。另外,因為使用了新的檔案鎖定方法,我也重寫了女聲訂閱程式的流程。女聲訂閱程式流程還要再改寫,以解決另一個問題:檔案最後更新日期的判定方式。

其次,我也寫了自訂的 HTTP 500 伺服器內部錯誤訊息,並欄截了開檔錯誤,產生 HTTP 500 訊息,以解決網站管理程式重建網頁時,網頁明明沒有更新,卻毫無警告訊息的老問題。

10 月 27 日那個週末是另一次重期的日期。我把之前想得到所有的大小 bug ,利用兩天三夜的周末假期都解決了。分列如下:

  1. 欄截了所有的檔案讀寫和其它系統函式的錯誤,並產生 HTTP 500 錯誤訊息,以更嚴密地保護程式正常運作。 HTTP 500 原本以 exit() 結束,改以 die 結束,在伺服器錯誤記錄中留下記錄。
  2. 重寫訪客計數器的流程,減少不必要的檔案鎖定,避免計數器卡死。計數器改以 grep() 判定內部位址。
  3. 摸清楚了 cookies 的詳細運作傳遞方式,簡化了計數器的 cookies ,停用 CGI::Cookies 模組,改用 CGI::header() 簡化處理。
  4. 摸清楚了 GD 模組的運作方式,簡化了計數器、最後更新日期、訂戶人數圖形的處理。
  5. 找到了判別網路作業系統的方式,改寫了 Win32 下的安全管制判別流程,並改以 getgrnam()getpwnam() 來做 Linux 下的安全管制。

10 月 28 日星期六,我改寫了所有網站管理程式的介面和資料庫,把關鍵字加上去,終於把不同的關鍵字整合進網頁中。我想做好網頁的關鍵字系統已經想了很久了。我順便改寫了相關連結的設定介面,提供更大的功能和彈性。另外,我也寫了旅舍的著作權聲明和隱私權聲明,並把旅舍中的女聲著作權聲明連結到女聲去。

隱私權聲明是我之前一直想寫的。既然前一天我把 cookies 的傳遞細節弄清楚了,就順便一起寫出來。希望這可以提醒大家不要在網路上亂留個人資料。至於著作權聲明嘛…原則上我很討厭著作權這種玩意兒。可是最近有些商業網站太過份了,而且有些莫名其妙的人開始對我的網站和我的文章感興趣。(不知道我招惹到什麼了?)為了避免不必要的麻煩,還是寫清楚比較好。

10 月 29 日星期天,我改進了自訂錯誤訊息,欄截自訂錯誤訊息本身的開關檔錯誤,並在發生自訂 HTTP 500 伺服器內部錯誤時,寄一封信通知網站管理者。

解決了之前另一個問題:因為程式無法處理 If-Modified-SinceHTTP 標頭,而且最後更新日期按照先前所述,會追溯到先前的留言日期,導致瀏覽器在重讀網頁時,快取的日期和資料內容錯亂,使瀏覽器卡死。我決定捨棄前述的最後更新日期算式,改以留言板程式本身和留言板資料檔的最後更新日期為準,以方便瀏覽器快取資料更新。我並且加上了對 If-Modified-Since HTTP 標頭的支援,加上了 HTTP 304 Not Modified 自訂訊息,以支援瀏覽器快取功能。

我寫了自訂 HTTP 405 Method Not Allowed 錯誤,避免有人用 PUT / DELETE / TRACE 等…連上來。雖這種事情應該不可能發生,可是一旦發生了卻沒有處理,是很笨的事。

到這裏,網站程式算是告一段落。我想得到的大小問題解決得差不多了,也鬆了一大口氣。

11 月 2 日,旅人留言簿資料已經接近 600筆,原來的資料庫引擎已經超出負荷,出現嚴重停滯現象。經過執行速度比對實驗後,我改寫了資料庫引擎。原來程式是一筆一筆比對,改用整批比對的方式,雖然有點取巧,但大幅度加快了資料庫解析速度。現在的新資料庫引擎,即使超過 6,000 筆留言,仍保持極快的速度。超過 10,000 筆以後呢?那以後再說吧。原則上,留言簿留言我不打算用 SQL 資料庫,維持最基本的原則:可攜性。我希望整個網站隨時可以搬到別的伺服器上,不需要依賴外在環境的特殊因素,例如:是 MySQL ? mSQL ? PostgreSQL ? MS-SQL ? Access ODBC ?還是 IBM DB2 ?

因為網站工程告了一段落,我開始打算釋出旅舍依瑪的原始程式碼。這個工程有點浩大,因為即使我程式碼寫得很清楚,可是註解卻不多,如果要釋出,還要加上很多註解,才能讓別人看得懂。

前天 11 月 3 日週末,我嚐試把旅舍搬回 Win32 IIS 的環境下,發現問題遠比我想像的複雜。 PerlIS 無法正常處理 HTTP 標頭、 IIS CGI 無法正確設定程式執行目錄, Apache mod_perl Apache::Registry 模組處理 CGI::header() 的方式也很特殊。我花了三天、翻遍 Perl 、mod_perl 的說明和討論以後,總算寫出程式,改用絕對檔案路徑,以取得最大的相容性,並根據特殊情形修正 HTTP 標頭。我並且解決了前述的問題: mod_perl Apache::Registry 模組下, CGI::header() 自訂 HTTP 錯誤會自動加上內文,導致內文長度錯亂亂,瀏覽器無法判別的問題。現在程式若是在 mod_perl 下,不會送出自訂錯誤訊息內文,將內文交給 mod_perl 處理。

我重寫了圖形程式(計數器、上次更新日期、訂閱人數)處理流程,以和其它程式的流程慣例一致。

想做的事還有一些。女聲訂閱程式的流程還要再改寫,先處理訂閱要求,再判斷最後更新日期。現在的順序是倒過來的。另外,要加強程式的註解,才能釋出程式碼。而且,還要加上記錄網站版本的變更。

釋出程式碼其實沒什麼大不了。現在的留言板、計數器的免費程式碼到處都是。但總是一個重要的里程碑。


目錄 | 第一頁 | 前一頁 | 1 | 2 | 3 | 4 | 5 | 下一頁 | 最末頁