2011年12月8日 星期四

繞路,沒啥不好的

竹東火車站


今晚挑了一間不曾去過的火車站,到那邊兌換車票,碰到了不熟票務系統的站長,大概是正逢早班晚班交接吧,看著他小慌地處理事情,我倒覺得有股溫馨的氣氛,不用著急外頭的車是否擋到別人,因為此刻的車站人煙稀少。我喜歡這樣的步調,甚至舉一下手跳一下就可以摸到車站外的天花板呢。



前陣子幾天假到處晃晃,終點站拜訪了恩師,恩師看到我的體型就跟我說有空繞路走走也不錯,然而,這「繞路」卻也點醒我的心境。周末順便看了「翻滾吧!阿信」,看完電影後上個廁所,連牆上都寫著:


證嚴法師:「信心、毅力、勇氣,三者具備,天下沒有做不成的事。


是啊,其實有時不會太在意別人的眼光,就像 Steve Jobs 自傳裡寫的那句話,每天當作最後一天,在那個情境下,別人的眼光、壓力都將顯得膚淺的。好好把認為有價值得事,從頭到尾地實踐吧,真正對你自己負責的,還是你自己啊。


建立 Django、Subversion、Trac 開發環境之相關設定 @ Ubuntu 10.04 64-Bit Server

最近準備移機和備份資料,雖然把開發環境跟 Trac 綁在一起不是很好,但基於機器數量及資源管理方面,備份就暫且這樣吧 :P 目標:有 Django 環境、有 Trac 環境,其中 Trac 採用 Subversion 並提供 HTTP 存取方式,並且讓 Subversion 和 Trac 的帳密使用同一份。


安裝相關環境:


$ sudo apt-get install mysql-server apache2 subversion libapache2-mod-python libapache2-svn libapache2-mod-wsgi python-mysqldb python-django ipython trac


設定 Subversion 環境:


挑選 /var/svn/repository 目錄為例


$ sudo mkdir -p /var/svn/repository
$ sudo chown -R www-data:www-data /var/svn/repository 


建立一個 Trac 環境:


挑選 /var/local/trac 目錄為例


$ sudo mkdir -p /var/local/trac
$ sudo chown -R www-data:www-data /var/local/trac 


設定 Apache Web Server 環境:


設定檔位置以 /etc/apache2/ 為例


設定帳密:


$ sudo touch /etc/apache2/dav_svn.passwd
$ sudo htpasswd /etc/apache2/dav_svn.passwd username 


設定 Subversion 部份:


可以挑選 /etc/apache2/mods-available/dav_svn.conf 和 a2enmod
此例用 /etc/apache2/site-available/svn.conf 和 a2ensite 


$ sudo vim /etc/apache2/site-available/svn.conf


<IfModule !dav_svn_module>
    LoadModule dav_svn_module modules/mod_dav_svn.so
</IfModule>
<IfModule !authz_svn_module>
    LoadModule authz_svn_module modules/mod_authz_svn.so
</IfModule>
<IfModule dav_svn_module>
<IfModule authz_svn_module>
<Location /svn>
    DAV svn
    SVNParentPath /var/svn/repository
    AuthType Basic
    AuthName "Subversion Repository"
    AuthUserFile /etc/apache2/dav_svn.passwd
    Require valid-user
</Location>
</IfModule>
</IfModule>


$ sudo a2ensite svn.conf
$ sudo /etc/init.d/apache2 reload 


如此一來,提供 http://localhost/svn/ProjectName 的存取機制,並採用 dav_svn.passwd 帳密管理


設定 Trac 部份:


可以挑選 /etc/apache2/mods-available/trac.conf 和 a2enmod
此例用 /etc/apache2/sites-available/trac.conf 和 a2ensite


$ sudo vim /etc/apache2/site-available/trac.conf


<IfModule !python_module>
    LoadModule python_module modules/mod_python.so
</IfModule>
<IfModule python_module>
    <location /projects>
        SetHandler mod_python
        PythonHandler trac.web.modpython_frontend
        PythonOption TracEnvParentDir /var/local/trac
        PythonOption TracUriRoot /projects
    </location>
    <locationmatch "/projects/[^/]+/login">
        AuthType Basic
        AuthName "Trac Authentication"
        AuthUserFile /etc/apache2/dav_svn.passwd
        Require valid-user
    </locationmatch>
</IfModule>


$ sudo a2ensite trac.conf
$ sudo /etc/init.d/apache2 reload 


如此一來瀏覽 http://localhost/projects 就可以看到 Trac 清單,並且登入各個 Trac Project 時,採用 dav_svn.passwd 帳密管理


建立一個 Project:


建立 Subversion project:


$ sudo -u www-data svnadmin create /var/svn/repository/mysite


建立 Trac project:


$ sudo -u www-data trac-admin /var/local/trac/mysite initenv
Project Name [My Project]> mysite
Database connection string [sqlite:db/trac.db]>
Repository type [svn]>
Path to repository [/path/to/repos]> /var/svn/repository/mysite


建立 mysite Trac 管理者(須先建立於 /etc/apache2/dav_svn.passwd 中):


$ sudo -u www-data trac-admin /var/local/trac/mysite/ permission add username TRAC_ADMIN


如此一來,就可以從 http://localhost/projects/mysite 進入 Trac 了,更可以用 username 登入後進去 Trac 管理者頁面進行設定,例如把 anonymous 權限刪掉,或是修改 authenticated 的權限,限制成員以外的只能 WIKI_VIEW 等,如果想要限制使用者能觀看哪些 page 的話,那可以試試 plugin TracTags 和 TracFullBlogPlugin 等。


挑選 ~/projects 目錄為例,作為儲存程式碼的地方:


$ mkdir ~/projects


建立 Django Project:


$ cd ~/projects
$ django-admin startproject mysite
$ cd ~/projects/mysite
$ django-admin startapp myapp


測試連線:


$ python manage.py runserver 0.0.0.0:8000


設定 Django 採用 WSGI 啟動(可隨著 Apache Web Server 啟動關閉一起行動):


此例用 /etc/apache2/sites-available/mysite.conf 和 a2ensite 


建立 django.wsgi:


$ vim ~/projects/mysite/django-mysite.wsgi 


import os, sys
sys.path.append('/home/user/projects')
sys.path.append('/home/user/projects/mysite')
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()


設定 mysite apache:


以 Port 做為區分服務的機制,此例為 port 8000


$ sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/mysite


$ sudo vim /etc/apache2/sites-available/mysite


Listen 8000
<VirtualHost *:8000>
    WSGIScriptAlias / /home/user/projects/mysite/django-mysite.wsgi
    WSGIDaemonProcess mysite_demo user=user group=user processes=1 threads=10
    ServerAdmin webmaster@localhost


    DocumentRoot /var/www
    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    <Directory /var/www/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all
    </Directory>


    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>


    ErrorLog /var/log/apache2/error.log


    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn


    CustomLog /var/log/apache2/access.log combined

    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride None
        Order deny,allow
        Deny from all
        Allow from 127.0.0.0/255.0.0.0 ::1/128
    </Directory>
</VirtualHost>


$ sudo a2ensite mysite
$ sudo /etc/init.d/apache2 reload 


存入 Subversion project:


$ cd ~/projects/
$ svn co http://localhost/svn/mysite svn_mysite
$ mkdir ~/projects/svn_mysite/trunk
$ mv ~/projects/mysite/* ~/projects/svn_mysite/trunk
$ cd ~/projects/svn_mysite
$ svn add trunk
$ svn ci -m 'init django project'
$ cd ~/projects
$ svn co http://localhost/svn/mysite/trunk mysite
$ rm -rf ~/projects/svn_mysite
$ cd ~/projects/mysite
$ svn info
Path: .
URL: http://localhost/svn/mysite/trunk
Repository Root: http://localhost/svn/mysite
Repository UUID: ########-####-####-####-##########
Revision: 1
Node Kind: directory
Schedule: normal
Last Changed Author: user
Last Changed Rev: 1
Last Changed Date: 2011-12-08 21:00:00 +0800 (Thu, 08 Dec 2011)


匯入:


$ sudo cp -r your_trac_project /var/local/trac
$ sudo cp -r toyr_svn_project /var/svn/repository/
$ sudo chown -R www-data:www-data /var/local/trac /var/svn/repository/


Update Path info:


/var/local/trac/*/conf/trac.ini


authz_file = /var/local/trac/*/conf/authzpolicy.conf


收工!


2011年11月16日 星期三

更新 Apache Web Server (2.2.14 > 2.2.16 > 2.2.17 > 2.2.20 或 2.2.21) 和 Django (mod_wsgi) 部份 @ Ubuntu 10.04

實在是有人太好心了,一直要掃我的機器,然後又跟我說機器上安裝的 httpd 太舊 Apache/2.2.14 (Ubuntu),因此需要更新軟體版本。我原先只會用 tarball 方式安裝,這次強者同事也提出很讚的解法(更新repositories),透過 /etc/apt/sources.list 慢慢新增 Ubuntu 10.10、11.04 甚至 11.10 的方式,在更新指定的套件,也能做到不錯得效果,如:


$ sudo vim /etc/apt/sources.list
#deb http://us.archive.ubuntu.com/ubuntu/ oneiric main #11.10
#deb http://us.archive.ubuntu.com/ubuntu/ natty main  #11.04
deb http://us.archive.ubuntu.com/ubuntu/ maverick main #10.10

$ sudo apt-get update
$ sudo apt-get install apache2
$ apache2 -v


例如以 apache2 為例,原先在 10.04 是 2.2.14 版本,先增加 10.10 來源,用 sudo apt-get update && sudo apt-get install apache2 更新 apache2 部份,得到 2.2.16 版本,若此版本不夠新,在換成 11.04 來源,一次使用一個來源,再繼續更新,直到版本符合需求,以 Apache Web server 為例:


10.04:Apache/2.2.14 (Ubuntu)
10.10:Apache/2.2.16 (Ubuntu)
11.04:Apache/2.2.17 (Ubuntu) 
11.10:Apache/2.2/20 (Ubuntu) 


同事建議循序更新,以免碰到軟體相依性問題。並且安裝完後再把新增得來源註解掉,再重新 apt-get update 一次。


另外,若想透過 tarball 更新的話,就直接在網路尋找來源,此例是更新為 Apache 2.2.21。優點是可以拿到最新版本,最大缺點卻是脫離系統原先軟體管控的架構,該套軟變成孤兒需要自行維護。


目前打算保留原先安裝的 apache 2.2.14 環境,直接用 tarball 來更新到 2.2.21,此例包括安裝 mod_wsgi 部份:


移除內建 Apache 的開機自動執行:


$ sudo update-rc.d -f apache2 remove


安裝開發環境:


$ sudo apt-get install gcc libssl-dev libexpat-dev python2.6-dev


安裝位置以~/tarball 為例:


$ cd ~/
$ wget http://apache.stu.edu.tw//httpd/httpd-2.2.21.tar.gz
$ tar -xvf httpd-2.2.21.tar.gz
$ cd httpd-2.2.21
$ ./configure --prefix=/home/user/tarball --enable-ssl
$ make install


$ cd ~/
$ wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
$ cd mod_wsgi-3.3
$ ./configure --with-apxs=/home/user/tarball/bin/apxs 
$ make install


設定開機啟動:


$ sudo ln -s ~/tarball/bin/apachectl /etc/init.d/apache2.2.21.sh
$ sudo update-rc.d -f apache2.2.21.sh defaults


除此之外,還需更新 httpd 的設定,設定檔就改到 ~/tarball/conf 裡頭,如此一來,就算是設定完成了


我想,如果沒特別的需求,還是透過強者同事建議的方式進行更新就好,以免很多套件需要更新時,就變成各自維護的情境了。


2011年11月12日 星期六

browser + web server + cgi = ??

01


看到 web app (HTML5+Javascript+CSS) 在 mobile 上應用的威力後,開始想要一個類似在 Windows 運作的平台,如 PhoneGap 幫你把 web app 包成 native app 的方式等,此原理就是用一個含有 UIWebView/WebView 的元件呈現指定的 web app 等,成果類似開啟瀏覽器呈現某個網址內容等,然而,在 PC 上有沒類似的平台?有的,那就是眾多的 Chrome extension、 Chrome Web app 和 Firefox plugin 等。


而 mobile 採用 Webkit 元件,如 UIWebView 於 iOS、WebView 於 Android 上,我開始在想能不能也有類似的情境用在 PC 端呢?例如 Webkit 於 Windows 上?但我不想直接拿 Safari Windows 或 Chromium Windows 來用,所以,我開始想惡搞小東西。


除此之外,以一個 WebView 元件,大多只能執行 Javascript 來作事,有沒可能執行 CGI 呢?對 mobile 上,以 Android 和 iOS 上,的確有一些架構可以巧妙地達成,對於 PC 平台,通常就是架一個 web server + cgi 功能。這樣的好處是讓習慣在 server 端寫 web app 的開發者,可以專心寫 web app 然後又可以運行在 PC 上。


總結一下,打算做的東西將提供的功能:



  • Windows 平台

  • 支援 HTML5/Javascript/CSS 環境

  • 支援 CGI 環境


為啥挑 Windows 平台?對 Open Source 開發者來說,不少對 Windows 很反感,但不可否認的,在 UI 和 App 數量上,Windows 有傑出的表現,簡單說那就是 OS 市占率還是 Windows 最高,例如遊戲平台大多都是 Windows 吧?或是周遭親友都還在用 Windows 吧!並且 Unix 環境上搞那小東西,反而更加無意義,因為下一個小指令,整個 web server 不就都裝好了 :P 所以我挑選 Windows 平台來惡搞。


實作的元件:



  • Chromium Embededd Framework (Browser)

  • Nginx 1.0.9 on Windows (Web server)

  • PHP 5.3.8 VC9 x86 Non Thread Safe (CGI)


成果:


http://web-apps-platform-on-windows-client.googlecode.com/files/YYWebAppsPlatformOnWindows-1.0.zip


用法:



  • 將程式碼擺在 nginx\html 目錄,當程式開啟自動瀏覽該目錄的 index.php 檔案

  • 此程式解壓縮後,請避開使用桌面、包含空白等位置 (有空再來處理)


應用情境:



  • 透過 HTML5、PHP 開發 Windows 視窗應用程式

  • 使用者使用時就像打開一般的視窗程式,接著操作畫面為 Web UI,使用者不須自行安裝和管理 Web server 等環境


主要會想搞這種東西的理由之一,是不想啥東西都要擺在 server 上頭,並且 Windows 的普及性的關係,如果可以提供一個 client 端的平台來運行 web apps 的話,這樣就可以方便得把程式散佈出去,並且不須網路連線也可以運作。更實際的應用例子,可以用在一些小案子上頭,幫別人做做單機版管理方面的應用服務等。




2011年11月7日 星期一

使用 VC++ 2010 Express 編譯 Chromium Embedded Framework (CEF) @ Windows 7 64-Bit

前一陣子接觸了 Webkit 和 Chromium 後,開始萌生一些小點子,雖然這些點子還滿粗淺的,但還是試看看吧。第一步則是要使用 Chromium Embedded Framework (CEF),並且嘗試編譯一下。


至於什麼是 CEF 呢?簡單說就是一個 library,讓你很容易在視窗程式中使用瀏覽器元件,若是以 mobile app 環境上,大概是 UIWebView @ iOS 和 WebView @ Android 吧。由於打算以免費的編譯環境,因此採用 VC Express 版本,設定上需要小小動一下。


編譯環境:


VC++ 2010 Express
VC++ 2010 Express SP1 
Windows Driver Kit Version 7.1.0


程式碼:


cef_binary_r306_windows.zip (42.0 MB)


設定:



  1. 開啟 cefclient2010.sln 檔

  2. [工具]->[設定]->[專家設定] && [檢視]->[屬性管理]-> 隨便一個 Project -> Debug | Win32 -> Microsoft.Cpp.Win32.user -> VC++ 目錄

    • Include 目錄

      • C:\WinDDK\7600.16385.1\inc\atl71

      • C:\WinDDK\7600.16385.1\inc\mfc42



    • 程式庫目錄

      • C:\WinDDK\7600.16385.1\lib\ATL\i386

      • C:\WinDDK\7600.16385.1\lib\Mfc\i386





  3. 設定 atldef.h 

    • C:\WinDDK\7600.16385.1\inc\atl71\atldef.h

    • 註解 //#error Do not define _SECURE_ATL.



  4. 設定 cefclient 專案

    • 屬性 -> 連結器 -> 輸入 -> 其他相依性 -> 增加 atlthunk.lib 即可




如此一來,即可編譯成功。唯一的缺陷是有警告訊息:


2>atlsd.lib(stdafx.obj) : warning LNK4078: 發現多個 'ATL' 區段有不同的屬性 (40301040)
2>clientplugin.obj : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>plugin_test.obj : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(atltrace.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(externs.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(atldebugapi.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(atlbase.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(atlfuncs.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(stdafx.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(allocate.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)
2>atlsd.lib(atltracemodulemanager.obj) : warning LNK4254: 區段 'ATL' (50000040) 以不同的屬性合併到 '.rdata' (40000040)


雖然網路上有查到相關解法(屬性 -> 一般 -> ATL 用法 -> 選擇"動態連結 ATL"或"靜態連結 ATL"),但測試的情況並沒有完全清除訊息,因此就先不管他了。接著有空慢慢以這個 cefclient2010.sln 當作基底,修改成想要的東西好了 :D


cefclient_win.cpp