什麼是 CGI?

它可以作什麼? CGI 是 Common Gateway Interface 的縮寫,它可以連結網路主機端與瀏覽器端,
使其能夠作檔案存取等動作的一種介面,CGI 程式就是可達成前述動作的程式,這是一種通稱而不是指某種特定的程式,
CGI 程式可以使用多種電腦語言來撰寫,依據作業平台的不同最常見的有 C、C++、Perl、PHP、TCL、JAVA、VB....等,
而大家在不同網頁上所見到的留言板、討論區、計數器、票選、寄賀卡、線上人數....等,都是屬於 CGI 程式的一種。

在網路上較常見的 CGI 程式多數是使用 Perl 語言撰寫的,因為它幾乎可說是專門為了撰寫 CGI 程式而量身打造的一種電腦語言,而且可使用的平台也較廣,如果是使用 VB 來撰寫 CGI 程式,那就只能在 Windows 平台上執行,若使用 C 語言來撰寫 CGI 程式,那麼就必須要在不同的作業平台上重新編譯過,否則是不能正常運作的。

Perl 語言是一種解譯式 (或稱直譯式) 的電腦語言,因此是以原始碼的型態散播的,它的語法基本上與 C 極為類似,
許多學習 CGI 程式的人都是由觀摩他人撰寫的 Perl 程式,進而修改成自己想要的介面或功能來入門的,
Perl 比較特別的是正規表示式 (Regular Expressions),功能非常非常的強大,但是因為是以符號所組成的一些處理規則,所以常常有初學者因為懶得查閱文件所以被它給打敗,如果您能在參考他人的程式時勤查文件來對照,其實學習起來並不難!

但是網路上雖然較常看到以 Perl 語言所撰寫的 CGI 程式,但是 CGI 與 Perl 並不等於是同義字,請不要將名詞弄混了,
如果是請教有關 Perl 語言所撰寫的程式問題,就寫明請教的是有關 Perl 語言的語法或流程等,
"CGI" 與 "CGI 程式" 也一樣不等於是同義字,"CGI" 一詞僅指 "通訊協定",而 "CGI 程式" 才是指 "程式"。

檔案格式與屬性設定: 以上兩個檔案可以使用一般的文字編輯程式來製作,
儲存時必須以標準的 ASCII 格式來存成文字檔,而上傳時也必須使用 ASCII 模式來上傳。


如何上傳 CGI 程式及設定程式檔案的屬性?

有些站台允許使用 Telnet 及 FrontPage 來上傳檔案,但是通常一般站台都採用 FTP 程式來處理上傳及下載檔案,
有些網友未看清楚站台的相關規定,而採用不適合的程式來上傳檔案,這是容易發生問題的。

如果您的 CGI 程式是使用 Perl 來撰寫的,因為 Perl 程式是屬於文字型態的檔案,所以您必須以 ASCII 模式來上傳。


設定檔案屬性:

首先您必須認清一個觀念:您自己個人電腦上的檔案無需也無法設定屬性,
同時也必須區分清楚哪一個操作視窗內的檔案是屬於網站上的檔案?

當您使用 FTP 程式接通網站後,檔案列表中所顯示出來類似 -rwxr-xr-x 這樣的標示就是檔案屬性的狀態,
在 UNIX 主機上檔案屬性分成三段,分別是:Owner、Group、Public (有的程式本項命名為 Other),
而每一段又分三種權限的設定,分別是 Read、Write、Exectue,一般的 FTP 程式都可以使用滑鼠右鍵呼叫出一個功能選單來更改檔案或目錄的屬性,通常該項功能的名稱叫做 Change file attributes 或是 chmod....等的。

當您要設定網站上的檔案屬性時,必須先將滑鼠指標移到欲更改的檔案名稱處,然後按下滑鼠左鍵將檔案名稱呈反白標示 (有些 FTP 程式允許同時標註多個檔案)。 接著再按下滑鼠右鍵,此時會顯示一個突現式功能選單,
如果您使用的是 CuteFTP 程式,那就選擇 "Change file attributes" 項目,如果您使用的是 WS_FTP 程式,
那就要選擇 "chmod (UNIX)" 的項目,如果您使用的是其它的 FTP 程式,那麼請參考該程式相關文件的說明來設定。

當畫面上出現一個設定屬性的操作視窗時,您可以依據要設定的屬性來圈選相對應的九個小方框,
各項目對應屬性碼的規則如下:

區分 Owner Group Public (Other) Read 400 40 4 Write 200 20 2 Exectue 100 10 1 前述例子中的 -rwxr-xr-x 屬性碼為 755,計算方式如下: Owner 的 RWX 加上 Group 的 RX 再加上 Public (或 Other) 的 RX。

Owner 的 400 + 200 + 100 加上 Group 的 40 + 10 再加上 Public (或 Other) 的 4 + 1。
將前述的數字加總就變成 700 + 50 + 5 = 755。

如果您使用的是 CuteFTP 之類的程式,在您圈選屬性權限項目時,會有一個長方框顯示點選後的屬性數字狀態,而您也可以選擇在該方框內輸入直接屬性數字。 雖然每個 FTP 程式的功能都是大同小異,但是卻都有不同的操作方式及功能名稱,如果您使用的是其它的 FTP 程式,您可以參考您使用 FTP 程式中的 Help,或利用搜索引擎找尋更多的解說資料來參考。


何謂真實路徑?什麼又是相對路徑?

真實路徑:

實體路徑就是真實的路徑,而不是經過系統處理過後的對應路徑,對應路徑可以用一個簡單的代名來取代一串長長的真實目錄名稱,或者是一組多層目錄的真實路徑,所以也可以說它是虛擬路徑,就像是在 Windows 系統的 DOS Box 裡以 SUBST 這個指令來設定虛擬磁碟是一樣的,例如以 X: 磁碟來代替 C:\次目錄\MySite\Data 這個路徑,那麼當您使用 DIR 指令查看 X:\ 時,其實看到的是 C:\次目錄\MySite\Data 這個目錄裡的資料。 當我們使用瀏覽器來觀看網頁資料時,透過 HTTPd 這個通訊協定來連結以 http:// 開頭的網址時,通常在網站系統這一端已經將網址對應到特定的目錄裡了,而以 http:// 開頭的網址我們可以說它就是一個對應路徑。 但是 CGI 程式在一般狀態下是無法對虛擬的對應路徑作實體上的讀寫動作,所以當程式內有作到檔案的讀寫動作時,就必須要使用真實路徑了,如果您使用的站台是 WIN32 的作業系統,那麼真實路徑就是 C:\次目錄\.... 之類的路徑名稱,如果是在 UNIX 或 UNIX-Like 的系統上,就是 /home/city1....
或是/home/user/public_html 之類的路徑名稱了。

相對路徑:

實體路徑與對應路徑都可以有相對路徑,在視窗系統及 UNIX-Like 系統上都是以 "." 來代表現在的目錄,而以 ".." 來代表上層的目錄,如果您在視窗系統的 DOS Box 中輸入 "dir .." 這個指令,那麼您將會看到上一層目錄的檔案列表資料。 如果我們在執行 CGI 程式時,要對不同目錄內的檔案作讀寫處理,那麼除了設定完整的真實路徑之外,也可以設定對應的真實路徑,舉例說明: 假設您的根目錄完整的真實路徑為 /home/usr/you,而目錄分佈如下: 根目錄 ┬ cgi-bin     └ data 而您在 cgi-bin 目錄內執行的某個 CGI 程式要讀取 data 目錄內名為 info.txt 的檔案時,因為程式在執行時的位置在 cgi-bin 這一個目錄內,所以必須以 ".." 來對應到上一層目錄,然後再指向名為 data 的目錄以及檔案名稱,因此在程式內設定讀取的相對路徑就變成 ../data/info.txt 這樣的敘述了,否則就得設定完整的真實路徑 /home/usr/you/data/info.txt。

如果您的 CGI 程式要讀寫的資料檔案與其放在同一個目錄內,那麼就無須設定路徑,或是設成 "./file.txt" 這樣的敘述就可以了。(記得前面講的嗎?"." 代表的是現在的目錄) 如果您要在 WIN32 系統中執行 CGI 程式,並且是把檔案路徑寫在程式裡的話,請將 C:\次目錄... 這樣的敘述改成 C:/次目錄... 這樣的敘述。 通常有支援 CGI 的站台都會有真實路徑的設定說明,否則請教在同一個站台設網頁的鄰居,或是寫信問網站管理員。


家裡測試網頁與 CGI 程式,我需要什麼軟體?

在 PC Windows 環境運作的 Web Server 常見的有 IIS (Internet Information Server) 及 WebSite 這兩套,
而大部分的 Perl 解譯環境則是 Perl for WIN32 (現更名為 ActivePerl),
IIS 是 Microsoft 公司的產品,WebSite 則是 O'Reilly 公司的產品!

(kuro補充:目前已有Apache for Win32可用)

ActiveState Tool 公司發行免費的 ActivePerl (Build 518) (5006KB) Microsoft IIS 3.0 Free for NT user

Microsoft Personal Web Server for WIN95 中文版 (750KB)

O'Reilly 公司發行的 WebSite 1.1 ,website-11e.exe (4042KB)

Xitami 2.5a1 (861KB) - iMatix 公司發行的免費 Web Server 軟體,程式不大功能卻不少

Sambar Server 4.3b2 (3,366KB) - Sambar 公司發行的免費 Web Server 軟體,功能頗完整的,還包含了 Perl 在內,無須另外安裝 Perl 解譯器。

基本的步驟如下:

參考說明文件所述步驟安裝 Web Server 系統。
參考說明文件所述步驟安裝 Perl。 安裝好後再重新開機,在 DOS Box 輸入 PATH 這個指令來查看搜尋路徑,
應該會增加 C:\Perl\bin; 這個目錄字樣。

設定相關目錄與存取權限。 若您使用的 Web Server 是 IIS,必須透過 IIS 的 "服務管理員"
將放置 CGI 程式的目錄設定 "執行" 的存取屬性,否則 CGI 程式將無法執行,使用 "服務管理員" 的設定步驟如下:

內容 → 服務內容 → 目錄 → [點選目錄] → 編輯內容 →
[在最下方的 "存取" 項目中的 "讀取" 及 "執行" 兩項都圈選起來]

測試: 設好呼叫 CGI 程式的 HTML 網頁檔內的設定,然後設定 CGI 程式內的相關設定,尤其是兩者對路徑的設定。

先在 DOS Box 中輸入指令 Perl -c testcgi.pl ← 使用 -c 參數可以檢查 testcgi.pl 程式內的語法是否正確?
若有錯誤會列出程式發生錯誤的行數及錯誤的說明。
(本項功能並無須配合 Web Server 使用,所以您可以利用本項功能在任何時間對 Perl 程式來作基本的測試)

啟動 Web Server,然後使用瀏覽器載入呼叫 CGI 程式的 HTML 網頁檔來執行 CGI 程式。
若發生問題,依據提示的訊息查閱說明文件中有關錯誤排除的章節。

如果發現有任何問題或是想要查閱某個指令的用法,您可以在 DOS Box 中使用 perldoc 這個指令檔來查閱相關資訊,
例如您想查看有關 flock 的說明,那您可以輸入 perldoc -f flock 這樣的指令敘述就可以了。

若測試無誤,應修改網頁檔及程式檔內與路徑相關的設定參數,然後上載到網頁所屬的網站上。
上傳至網站後亦應再作實際的相關測試,以確保程式在網站上能正確的執行。 撰寫 CGI 程式需要哪些工具?

使用 Perl 語言所撰寫的 CGI 程式係以解譯 (直譯) 的方式來執行的,因此程式檔案是以原始碼的方式呈現的,
所以您必須使用 "記事本" (notepad.exe) 之類的純文字編輯程式 來建立或編修 Perl 程式檔案,
如果您因為習慣的問題而使用 MS-Word 之類的程式來編修程式檔案也是可以的,
但是請記得存檔時要選擇儲存成 "純文字" 的格式。

既然程式在自己的電腦撰寫好,也經過測試無誤的話,那麼您可能會想將程式上傳到網站上來正式的運作,
上傳檔案的方式很多種,但是通常是使用 "FTP 程式" 來處理。

如果提供您放置 CGI 程式的網站採用的是 UNIX 或是 UNIX-Like 的作業系統,那麼您可能必須要對上傳到網站上的程式檔案作屬性的設定,如果該站台提供您使用 telnet 的方式進入網站,那麼您可以使用 chmod 指令來對檔案作屬性的設定,但是一般有提供支援 CGI 程式運作的網站,通常都是提供 FTP 的方式來供用戶處理檔案,因此您就需要使用到 FTP 程式。


問題與解答:

Q:為何我的留言板程式可以正常執行,但是卻無法將新的留言寫入檔案內?

A:可能是因為資料檔的寫入權限或屬性設定不足所致。

Q:為何我在家裡用 Windows 95 測試我的 Perl 程式可以正常執行,上載到網站上之後卻不能執行?

A:網站上通常都有一些設定與要求是與自己在家裡使用的環境不相同,因此這種情形一但發生,
 就必須針對不同的網站作一些不同的測試,然後才能找出切確的原因,但是我可以建議您檢查一下權限與屬性的設定。

Q:我的網頁設在北美地區,但是我希望留言板紀錄的是台北時間,我該怎麼做?

A:只要設定時區或是換算時區的相對時間就可以了,以下兩種方式都可以取得相同的結果:
 將取得的時間加上(或減掉)格林威治時間: $mytime = gmtime(time+8*60*60);
 其中的8是時區與 GMT 的時差數,台北是 +8、夏威夷是 -10....依此類推。
 在原本處理時間取的敘述之前加上時區代名的設定: $ENV{TZ} = 'Asia/Taipei'; $mytime = localtime(time);

Q:執行 CGI 程式時出現如下的訊息:
 The requested method POST is not allowed for the URL /..../cgi-bin/test.pl

A:test.pl 這支程式的屬性未設正確,無法執行該程式。

Q:如何排除 Perl 程式處理中文資料的障礙?

A: 在 CGI Perl 程式中,有許多符號字元是有特殊用途的,而不幸的有某些這樣的字元卻與

  中文字的第二個位元組互相衝突,以至於會有中文字顯示或比對不正確,甚至是產生
  錯誤結果的現象,尤其是 | 及 \ 這兩個字元,所幸我們還有個 quotemeta 指令可以使用,這個指令可以將指定的字串
 每個字元的前面都再多加上一個 \ 這個字元,使得字串內的特殊字元在處理時被視為單純的字碼,請參考下列的範例:

  假設 $str 是一個要做搜尋比對的中文字串,而 $line 是逐行讀入的資料檔內容:

$restr =quotemeta $str; if ($line !~ m/$restr/i) { ...... }

另外若不是以變數來處理的字串,通常我們會
使用雙引號來標示及處理,然而這也是會發生上述的障礙,
但是當您直接對雙引號括
住的字串使用 quotemeta 來處理時卻又會怪怪的,那怎麼辦呢?

很簡單!將雙引號改為
單引號就可以囉∼因為單引號不會對其內的字元作特殊處理,
換句話講在單引號之內
的文字資料將會原原本本的呈現出來,不會去解譯變數也不會處理 escape 字元,
例如
原來的敘述是:

print "測試成功的$msg訊息!\n"; 應改為: print '測試成功的訊息!';
請特別注意 \n 換行符號及 $msg 變數也需拿掉,因為單引號並不處理 escape 字元及變數

如果不將 \n 符號及 $msg 變數拿掉,那麼顯示出來的字樣將會是 成功的$msg訊息!\n,
如果您仍希望顯示成原來包含變數及換行的效果,那就必須將單引號與雙引號資料併用,
同時以 . 符號來連結成完整的輸出敘述: print '成功的'.$msg.'訊息!'."\n";

上述結論就是當印出 成功的 與 訊息! 字樣是使用單引號,而換行的 \n 則是用雙引號。

Q:我要如何才能在 CGI 程式中將留言者填寫資料中的 HTML 標籤指令過濾掉?

A:假設 $val 是一個要做過濾處理的字串,若不是在特殊的狀態下,套用以下的敘述就可
以了:
$val =~ s/<(.|\n)*>//g; 或是: $val =~ s/<(([^>]|\n)*)>//g;

Q:執行 CGI 程式時出現如下的訊息: 500 Internet Server Error Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request Please contact the server administrator, root@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.

A:這個是代碼為 500 的錯誤,是指 "可能為任何的錯誤",因此範圍太廣無法由訊息來判斷問題所在,
 最可能發生的原因如下: 程式內有語法錯誤或設定錯誤之處,例如:行
尾少了分號....。
 程式或資料檔的屬性設定不正確,無法做完整的讀寫動作。
 沒有以ASCII 模式上傳 CGI 程式。 程式第一行 #!/..../perl 的路徑宣告不正確或不符合網站的要求。
 相關檔案的路徑設錯,例如留言板程式的 /..../sendmail或 /..../sendmail -t。

Q:執行 CGI 程式時出現如下的訊息: CGI wrap Error: User not in allow file!

A:未獲得 CGI 使用權限。 CGI 程式屬性設定不正確。

Q:執行 CGI 程式時出現如下的訊息: CGI wrap Error: Script File Not Found!

A: 不是檔案名稱設錯就是路徑不正確。

Q:執行 CGI 程式時出現如下的訊息: CGI wrap Error: Script is not executable. Issue chmod 755 ......

A: 將檔案屬性改為 755 就可以了。

Q:執行 CGI 程式時出現如下的訊息:
 CGI wrap Error: System Error: execv() failed Error: No such file or directory (2)


A:上傳時改用 ASCII 模式。 Perl 檔案的第一行沒有指定 #!/usr/bin/perl 或是 #!/usr/local/bin/perl
或路徑錯誤(各站台設置的位置可能不同)無法找到 Perl 解譯程式。


請您記得:並非所有站台都提供 CGI 的使用權,要在自己的網頁上使用 CGI 程式,
必須要先確認網頁所屬的站台是否有開放 CGI 的使用權給您,如果您想再多瞭解一些有關 CGI 及 Perl 的資訊,
或是想找有開放支援 CGI 使用權的站台,請多加善用搜索引擎來找尋,搜索引擎也是 CGI 程式的一種喔!


本頁面最後更新日期:01/20/2003