先前如果有完成 Optware 的設定後,現在就可以裝許多套件來玩了。這一篇主要著重於架設網路伺服器 (Web/HTTP Server) 的部分,查看套件列表可以發現也是有許多選擇,但是大家都不推薦安裝最常見的 Apache,理由非常簡單:跑不動。Apache 對於嵌入式系統的硬體來說實在是負擔過大,取而代之仍有許多輕量級的選擇: cherokee, lighttpd, nginx, thttpd, minihttpd 等。
thttpd - tiny/turbo/throttling HTTP server
官方網站:http://acme.com/software/thttpd/thttpd 在 Abin 的網誌「Abin's Tech Note: 支援 PHP 的網頁伺服器 (thttpd) 安裝設定」已經介紹過,我僅簡單介紹安裝過程:
ipkg install php-thttpd
或
ipkg install thttpd
這兩個最大的不同是有 php 前綴的是內建 PHP 支援的版本,而後者僅為單純的 HTTP Server。
thttpd 的設定檔位置在 /opt/etc/thttpd.conf,網頁根目錄則在 /opt/share/www。另外經過 Abin 等人的實際測試發現 php-thttpd 運作時似乎會有不穩的情形發生,Process 常常無緣無故消失而必須手動重新啟動。
lighttpd - fly light.
官方網站:http://www.lighttpd.net/LightTPD (發音同: Lighty) 是一套輕量級的 Web Server,正如副標 fly light. 它非常輕盈,運用在非常多知名的 Web 2.0 網站,大部份改機的人都推薦安裝此套件,加上 PHP FastCGI 來達成對 PHP 的支援。安裝指令:
ipkg install lighttpd php-fcgi
這個指令會安裝好 lighttpd 和 PHP FastCGI 環境,因為 PHP 的相依函式庫有很多所以需要一些時間。lighttpd 的設定檔位於 /opt/etc/lighttpd/lighttpd.conf。網頁根目錄則在 /opt/share/www。
修改設定檔
記得要先打開 /opt/etc/lighttpd/lighttpd.conf 修改 server.event-handler,可以改成:server.event-handler = "linux-rtsig"預設是註解的狀態,而且設定值也不對,沒有修改的話在嵌入式系統 Linux 2.4 是無法順利運作的!其實按照 Wiki 說明 poll 也可以,但 Kernel 2.4 版支援的 linux-rtsig 效果應該比較好。
由於剛才已經一併安裝了 php-fcgi,/opt/etc/lighttpd/conf.d/ 內會有 10-php-fcgi.conf,所以 Lighttpd 啟動後會一併自動啟動 PHP FastCGI,不必再做額外的設定,非常方便。但是我自己使用 lighttpd 遇到了一些問題。
自身測試遇到的問題
首先是 lighttpd 不能以 nobody 使用者運作。預設使用者是 admin 這非常危險。雖然設定檔內有 server.username 和 server.groupname 這兩個選項可以設定啟動的使用者和群組,但是兩個都設定成 nobody 後反而無法成功啟動,最多只能 server.groupname = nobody,變成使用者是 admin / nobody 群組的怪異現象。但如果不考慮安全性問題的話倒是無妨,但其實還有另一個大問題。第二個讓我決定移除 lighttpd 的原因是我只要放超過 512KB 的檔案,以瀏覽器要求檔案,進度會卡在 512KB 而無法完成要求。這是一個很奇怪的問題,我查遍各大網站都沒有像我一樣的案例,實在是鬼打牆。經過測試後發現應該是 lighttpd 本身的問題,因為我的 vsftpd 或者是等下會介紹的 nginx 傳輸完全正常,於是決定忍痛移除 lighttpd 了。如果你安裝完、測試下載超過 512KB 大小的檔案都沒問題,那恭喜你可以安心繼續使用了。不然就跟我一樣,使用接著會介紹的 nginx。
nginx
官方網站:http://nginx.org/nginx (發音同 Engine X) 是俄國程式設計師 Igor Sysoev 設計的輕量網頁伺服器/反向代理伺服器。噗浪 Plurk就是其中一個使用的知名 Web 2.0 網站。其效能常常跟 lighttpd 拿來比較,不相上下。唯一明朗的一點就是它們兩個都比 Apache 的效能要好。很奇怪網路上似乎找不到 Oleg 版韌體安裝 nginx 的說明,經過摸索並安裝成功後,我想我就來當第一人吧。
ipkg install nginx php-fcgi spawn-fcgi安裝 nginx、PHP FastCGI 和 FastCGI 管理器 spawn-fcgi。最後這個套件在安裝 lighttpd 的時候會自動安裝,但是 nginx 則不會,需要手動安裝。nginx 的設定檔位於 /opt/etc/nginx/nginx.conf。網頁根目錄則在 /opt/share/nginx/html。
修改 nginx 設定檔
打開 /opt/etc/nginx/nginx.conf,我們修改的目的有 1. "nobody" 使用者執行 2. 啟用 access.log 和 error.log 3. 設定 PHP FastCGI。user nobody;
將前面 # 刪除以取消註解 (1. "nobody" 使用者執行)
error_log logs/error.log;
將前面 # 刪除以取消註解 (2. 啟用 error.log)
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main;
將前面 # 刪除以取消註解 (2. 啟用 access.log)
location ~ \.php$ { root html; try_files $uri @404 fastcgi_pass unix:/tmp/php-fcgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location @404 { return 404; break; }
請改成上面的配置。(3. 設定 PHP FastCGI)
try_files 一段是先判斷 PHP 檔案是否存在才送給 PHP 執行,不然你要求一個不存在的 PHP 其 404 錯誤訊息並不是預設畫面而是奇怪的 "No input file specified." 錯誤。(FYI: Google 搜尋 FastCGI "No input file specified.")
fastcgi_pass 則是指定 PHP FastCGI 的路徑,這邊我們先設定好,後面還會再設定 FastCGI。
fastcgi_param 則是設定 PHP 檔案實際的路徑,如果設定錯誤的話則會出現錯誤。網路上的例子都是叫你改成 /var/www$fastcgi_script_name 一類的實際路徑,但其實有 $document_root 變數可以用,改成 $document_root$fastcgi_script_name 準沒錯。
最後追加的一行 location 則是跟 try_files 搭配,若是要求的檔案不存在,則回傳 404 錯誤頁面。原本沒有這一行記得加上去。(Source: 官方論壇 FastCGI returning "No Input File" instead of 404)
經過一番修改並儲存之後,接著是 PHP FastCGI的設定。
新增 PHP FastCGI 啟動設定檔
我們還要手動新增 PHP FastCGI 的啟動設定才行。因為 php-fcgi 這個套件對 lighttpd 比較好,已經幫它設定好了所以不必手動設定,使用其他伺服器的就只能手動設定了。本次的目的是設定 PHP FastCGI 讓它在開機時常駐。因此我們需要手動建立 /opt/etc/init.d/S80php-fcgi 檔案:(vi或nano) /opt/etc/init.d/S80php-fcgi
檔案內容直接按照以下內容複製貼上:
#!/bin/sh phpfcgid_children="1" phpfcgid_requests="1000" prefix="/opt" PATH=${prefix}/bin:${prefix}/sbin:/sbin:/bin:/usr/sbin:/usr/bin NAME=php-fcgi DAEMON=${prefix}/bin/spawn-fcgi DAEMON_OPTS="-s /tmp/php-fcgi.sock -C ${phpfcgid_children} -u nobody -P /var/run/php-fcgi.pid -- ${prefix}/bin/${NAME}" test -x $DAEMON || exit 0 if [ -z "$1" ] ; then case `echo "$0" | sed 's:^.*/\(.*\):\1:g'` in S??*) rc="start" ;; K??*) rc="stop" ;; *) rc="usage" ;; esac else rc="$1" fi case "$rc" in start) export PHP_FCGI_MAX_REQUESTS=$phpfcgid_requests echo "Starting web server: $NAME" $DAEMON $DAEMON_OPTS ;; stop) if [ -n "`pidof $NAME`" ]; then echo "Stopping web server: $NAME" killall $NAME 2> /dev/null fi ;; restart) "$0" stop sleep 1 "$0" start ;; *) echo "Usage: $0 (start|stop|restart|usage)" ;; esac exit 0
這個啟動檔主要是透過 spawn-fcgi 來建立 nobody 使用者的 php-fcgi 程序,並利用 Unix domain socket 方式建立 /tmp/php-fcgi.sock 檔案供 nginx 溝通。儲存檔案後記得還要給啟動檔執行權限:
chmod +x /opt/etc/init.d/S80php-fcgi
重新啟動 nginx 和 PHP FastCGI
這時候重新啟動 AP 就可以生效了,但也可以不必重新啟動便能發生效果,手動執行以下兩行指令便可以重新啟動:/opt/etc/init.d/S80nginx restart
/opt/etc/init.d/S80php-fcgi restart
如果沒有任何錯誤訊息產生,恭喜伺服器已經運作正常。
附錄: 使用記憶體量
Mem: 13092K used, 660K free, 0K shrd, 744K buff, 6060K cached CPU: 0% usr 38% sys 0% nic 61% idle 0% io 0% irq 0% sirq Load average: 0.00 0.02 0.04 2/30 1572 PID PPID USER STAT VSZ %MEM %CPU COMMAND 1377 1376 nobody S 22176 161% 0% /opt/bin/php-fcgi 1376 1 nobody S 21876 159% 0% /opt/bin/php-fcgi 853 852 nobody S 4100 30% 0% nginx: worker process 852 1 admin S 4072 30% 0% nginx: master process /opt/sbin/nginx
對外: 防火牆的設定
如果你只有對內的需求 (即透過 AP LAN IP 存取服務),就不必管防火牆。如果你有對外的需求,就必須先設定防火牆才可以運作正常。防火牆的設定檔案在 /usr/local/sbin/post-firewall,位於 flashfs 內。Oleg 的設計是要先將 Web 管理介面的 Internet Firewall 給關閉,系統才會去執行 post-firewall 檔案,因此請先將其關閉。就我直接觀察 iptables -L 的規則設定發現啟動或關閉此功能似乎沒有不同。(就算關閉了預設也還有一串規則)
關閉後重新啟動 AP,登入 Telnet/SSH 新增 /usr/local/sbin/post-firewall:
(vi 或 nano) /usr/local/sbin/post-firewall這次的目標是要開啟 8080 Port (視伺服器設定),並將外部 80 Port 的要求轉到內部的 8080。之所以這樣做的原因是因為 AP 的 80 Port 早就被 Web 管理介面給佔據了,於是另架的伺服器就只能選擇其他如 8080。但瀏覽器輸入 http://(外部IP):8080 瀏覽也不太方便,所以利用 Prerouting 的方式將一般外部 80 轉到內部的 8080。範例: http://www.example.com/ -> 192.168.1.1:8080
#!/bin/sh$1 是代表網路介面,通常也就是 eth0。第一行 iptables -D INPUT -j DROP 代表刪除 INPUT 的最後一個設定 (預設最後一個設定是封鎖全部),必須先拿掉我們才能打開Port,最後再補回來,中間則是設定開放 8080 和 Prerouting 80 to 8080,最後一行則是設定 INPUT 剩下的 Port 全部封鎖 (補回來)。由於 iptables 是逐行執行,最後一行的位置千萬不要放到自訂規則前了。
iptables -D INPUT -j DROP
# lighttpd / thttpd / nginx
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
iptables -t nat -A PREROUTING -i $1 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A INPUT -j DROP
然後記得給予執行權限,和寫回 flashfs:
chmod +x /usr/local/sbin/post-firewall
flashfs save && flashfs commit && flashfs enable
最後,重開 AP 讓整個設定能夠被執行,這樣防火牆設定和伺服器的架設就完成了。
reboot
測試成果
先在網頁根目錄新增一檔案:
echo "<?php phpinfo();?>" > /opt/share/www/phpinfo.php然後用瀏覽器瀏覽檔案 (http://內部IP:8080/phpinfo.php 或 http://外部IP/phpinfo.php),如果像圖一樣有 PHP 的資訊那就大成功啦。
另外瀏覽外部IP的電腦必須不是用 AP 的 NAT 上網方式來看,這樣只會看到 Web 管理介面。利用 PPPoE-relay 撥號取得實體 IP 再來看才看的到正確的結果,或使用其他與 AP 無任何連線的電腦上網看。
沒有留言:
張貼留言