2010年12月30日 星期四

PropelException [wrapped: SQLSTATE[HY000]: General error: 17 database schema has changed]

這個問題Debug了三天,快把我搞瘋

我在跑UnitTest


Drop Table A
Create Table A
public function testA_1()

Drop Table A
Create Table A
public function testA_2()


原因如下:
每次跑test method時,因為先把table drop掉當成truncate table來使用,所以才會出現這個Error

Solution:
不要用drop table

2010年12月27日 星期一

Linux 上 .a 跟 .so

Library可分成三種,static、shared與dynamically loaded。


1. Static libraries


Static 程式庫用於靜態連結,簡單講是把一堆object檔用ar(archiver)

包裝集合起來,檔名以`.a’ 結尾。優點是執行效能通常會比後兩者快,

而且因為是靜態連結,所以不易發生執行時找不到library或版本錯置而

無法執行的問題。缺點則是檔案較大,維護度較低;例如library如果發

現bug需要更新,那麼就必須重新連結執行檔。


1.1 編譯


編譯方式很簡單,先例用`-c’ 編出object 檔,再用ar 包起來即可。


____ hello.c ____

#include

void hello(){ printf(”Hello “); }


____ world.c ____

#include

void world(){ printf(”world.”); }


____ mylib.h ____

void hello();

void world();


$ gcc -c hello.c world.c /* 編出hello.o 與world.o */

$ ar rcs libmylib.a hello.o world.o /* 包成limylib.a */


這樣就可以建出一個檔名為libmylib.a 的檔。輸出的檔名其實沒有硬性規定,

但如果想要配合gcc 的’-l’ 參數來連結,一定要以`lib’ 開頭,中間是你要

的library名稱,然後緊接著`.a’ 結尾。


1.2 使用


____ main.c ____

#include “mylib.h”

int main() {

hello();

world();

}


使用上就像與一般的object 檔連結沒有差別。


$ gcc main.c libmylib.a


也可以配合gcc 的`-l’ 參數使用


$ gcc main.c -L. -lmylib


-L dir 參數用來指定要搜尋程式庫的目錄,`.' 表示搜尋現在所在的目
錄。

通常預設會搜/usr/lib 或/lib 等目錄。

-l library 參數用來指定要連結的程式庫,'mylib' 表示要與mylib進
行連結

,他會搜尋library名稱前加`lib'後接`.a'的檔案來連結。


$ ./a.out

Hello world.

2. Shared libraries


Shared library 會在程式執行起始時才被自動載入。因為程式庫與執行檔

是分離的,所以維護彈性較好。有兩點要注意,shared library是在程式起始

時就要被載入,而不是執行中用到才載入,而且在連結階段需要有該程式庫

才能進行連結。


首先有一些名詞要弄懂,soname、real name與linker name。


soname 用來表示是一個特定library 的名稱,像是libmylib.so.1 。

前面以`lib' 開頭,接著是該library 的名稱,然後是`.so' ,接著

是版號,用來表名他的介面;如果介面改變時,就會增加版號來維護相容度。


real name 是實際放有library程式的檔案名稱,後面會再加上minor 版號與

release 版號,像是libmylib.so.1.0.0 。


一般來說,版號的改變規則是(印象中在APress-Difinitive Guide to GCC中有

提到,但目前手邊沒這本書),最尾碼的release版號用於程式內容的修正,

介面完全沒有改變。中間的minor用於有新增加介面,但相舊介面沒改變,所以

與舊版本相容。最前面的version版號用於原介面有移除或改變,與舊版不相容

時。


linker name是用於連結時的名稱,是不含版號的soname ,如: libmylib.so。

通常linker name與real name是用ln 指到對應的real name ,用來提供

彈性與維護性。


2.1 編譯

shared library的製作過程較複雜。


$ gcc -c -fPIC hello.c world.c


編譯時要加上-fPIC 用來產生position-independent code。也可以用-fpic

參數。(不太清楚差異,只知道-fPIC 較通用於不同平台,但產生的code較大

,而且編譯速度較慢)。


$ gcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.0 \

hello.o world.o


-shared 表示要編譯成shared library

-Wl 用於參遞參數給linker,因此-soname與libmylib.so.1會被傳給linker處理。

-soname用來指名soname 為limylib.so.1

library會被輸出成libmylib.so.1.0.0 (也就是real name)


若不指定soname 的話,在編譯結連後的執行檔會以連時的library檔名為

soname,並載入他。否則是載入soname指定的library檔案。


可以利用objdump 來看library 的soname。


$ objdump -p libmylib.so | grep SONAME

SONAME libmylib.so.1


若不指名-soname參數的話,則library不會有這個欄位資料。


在編譯後再用ln 來建立soname 與linker name 兩個檔案。

$ ln -s libmylib.so.1.0.0 libmylib.so

$ ln -s libmylib.so.1.0.0 libmylib.so.1

2.2 使用


與使用static library 同。


$ gcc main.c libmylib.so


以上直接指定與libmylib.so 連結。


或用


$ gcc main.c -L. -lmylib


linker會搜尋libmylib.so 來進行連結。


如果目錄下同時有static與shared library的話,會以shared為主。

使用-static 參數可以避免使用shared連結。


$ gcc main.c -static -L. -lmylib


此時可以用ldd 看編譯出的執行檔與shared程式庫的相依性

$ldd a.out

linux-gate.so.1 => (0xffffe000)

[1;33mlibmylib.so.1 => not found[m

libc.so.6 => /lib/libc.so.6 (0xb7dd6000)

/lib/ld-linux.so.2 (0xb7f07000)

輸出結果顯示出該執行檔需要libmylib.so.1 這個shared library。

會顯示not found 因為沒指定該library所在的目錄,所找不到該library。


因為編譯時有指定-soname參數為libmylib.so.1 的關係,所以該執行檔會

載入libmylib.so.1。否則以libmylib.so連結,執行檔則會變成要求載入

libmylib.so


$ ./a.out

/a.out: error while loading shared libraries: libmylib.so.1

cannot open shared object file: No such file or directory


因為找不到libmylib.so.1 所以無法執行程式。

有幾個方式可以處理。


a. 把libmylib.so.1 安裝到系統的library目錄,如/usr/lib下

b. 設定/etc/ld.so.conf ,加入一個新的library搜尋目錄,並執行ldconfig

更新快取

c. 設定LD_LIBRARY_PATH 環境變數來搜尋library

這個例子是加入目前的目錄來搜尋要載作的library

$ LD_LIBRARY_PATH=. ./a.out

Hello world.

3. Dynamically loaded libraries


Dynamicaaly loaded libraries 才是像windows 所用的DLL ,在使用到

時才載入,編譯連結時不需要相關的library。動態載入庫常被用於像plug-ins

的應用。


3.1 使用方式

動態載入是透過一套dl function來處理。

#include

void *dlopen(const char *filename, int flag);

開啟載入filename 指定的library。

void *dlsym(void *handle, const char *symbol);

取得symbol 指定的symbol name在library被載入的記憶體位址。

int dlclose(void *handle);

關閉dlopen開啟的handle。

char *dlerror(void);

傳回最近所發生的錯誤訊息。


____ dltest.c ____

#include

#include

#include

int main() {

void *handle;

void (*f)();

char *error;


/* 開啟之前所撰寫的libmylib.so 程式庫*/

handle = dlopen("./libmylib.so", RTLD_LAZY);

if( !handle ) {

fputs( dlerror(), stderr);

exit(1);

}


/* 取得hello function 的address */

f = dlsym(handle, "hello");

if(( error=dlerror())!=NULL) {

fputs(error, stderr);

exit(1);

}

/* 呼叫該function */

f();

dlclose(handle);

}


編譯時要加上-ldl 參數來與dl library 連結

$ gcc dltest.c -ldl

結果會印出Hello 字串

$ ./a.out

Hello


關於dl的詳細內容請參閱man dlopen


--

參考資料:


Creating a shared and static library with the gnu compiler [gcc]

http://www.adp-gmbh.ch/cpp/gcc/create_lib.html


Program Library HOWTO

http://tldp.org/HOWTO/Program-Library-HOWTO/index.html


APress - Definitive Guide to GCC

2010年12月12日 星期日

How to extract/unzip RPM or DEB packages

Extracting the contents of the RPM package is a one step process:
$ rpm2cpio mypackage.rpm | cpio -vid

If you just need to list the contents of the package without extracting them, use the following:
$ rpm2cpio mypackage.rpm | cpio -vt

RHEL manual install php5.3.3+mysql5.1+apache2 and phpize pdo_dblib.so

# yum install relative package
$ yum install gcc gcc-c++ gcc-g77 flex bison autoconf automake bzip2-devel zlib-devel ncurses-devel libjpeg-devel libpng-devel libtiff-devel freetype-devel pam-devel

#(1) GD2
$ cd /usr/local/src
$ wget http://www.boutell.com/gd/http/gd-2.0.33.tar.gz
$ tar xzvf gd-2.0.33.tar.gz
$ cd gd-2.0.33
$ ./configure –prefix=/usr/local/gd2 –mandir=/usr/share/man //./configure 配置。
$ make //make 是用來編譯的,它從Makefile 中讀取指令,然後編譯。
$ make install //make install 是用來安裝的,它也從Makefile 中讀取指令,安裝到指定的位置。

#(2) Apache 日誌截斷程序
$ cd /usr/local/src
$ wget http://cronolog.org/download/cronolog-1.6.2.tar.gz
$ tar xzvf cronolog-1.6.2.tar.gz
$ cd cronolog-1.6.2
$ ./configure –prefix=/usr/local/cronolog
$ make
$ make install

#(3) libxml 庫程序
$ cd /usr/local/src
$ wget http://ftp.gnome.org/pub/gnome/sources/libxml2/2.6/libxml2-2.6.26.tar.gz
$ tar zxvf libxml2-2.6.26.tar.gz
$ cd libxml2-2.6.26
$ ./configure –prefix=/usr/local/libxml2
$ make
$ make install



$ groupadd mysql
$ useradd -g mysql mysql
$ gunzip < mysql-VERSION.tar.gz | tar -xvf -
$ cd mysql-VERSION
$ ./configure --prefix=/usr/local/mysql
$ make
$ make install
$
$ cp support-files/my-medium.cnf /etc/my.cnf
$ cd /usr/local/mysql
$ chown -R mysql .
$ chgrp -R mysql .
$ bin/mysql_install_db --user=mysql
$ chown -R root .
$ chown -R mysql var
$ bin/mysqld_safe --user=mysql &

4、編譯安裝Apache2.24
這個最簡單了,基本不會有錯誤發生。
$ yum -y install openssl openssl-devel
# tar zxvf httpd-2.2.17.tar.gz
# cd httpd-2.2.17
$ ./configure --prefix=/opt/httpd-2.2.17 --enable-modules=all --enable-mods-shared=all --enable-proxy --enable-ssl --enable-so --with-mpm=prefork --with-pcre
$ make -j8
$ make install
$ ln -s /opt/httpd-2.2.17 /opt/httpd
$ echo '
# Start Apache
/usr/local/apache2/bin/apachectl start' >> /etc/rc.local


編譯安裝curl
下載curl 安裝到/usr/local/curl


5、編譯安裝php5.3.3
./configure --prefix=/usr/local/php --with-apxs2=/opt/httpd/bin/apxs --with-config-file-path=/usr/local/php --with-openssl --enable-bcmath --enable-calendar --with-curl=/usr/local/curl --with-curlwrappers --enable-ftp --with-gd --with-jpeg-dir=/usr/local/jpeg --with-png-dir=/usr --enable-gd-native-ttf --with-gettext --enable-mbstring --enable-exif --with-mysql=/usr/local/mysql --with-pdo-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-xmlrpc --enable-soap --enable-sockets --enable-zip

$ make
$ make install
$ cp php.ini-recommended /etc/php.ini

$ yum -y install php-devel
1、安裝配置freetds
下載地址: http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
用以Linux和Unix連接MS SQLServer和Sybase數據庫。

$ wget http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
$ tar zxvf freetds-stable.tgz
$ cd freetds-stable
$ ./configure --prefix=/usr/local/freetds --with-tdsver=8.0 --enable-msdblib
$ make && make install

$ cd /usr/local/src/php-5.3.3/ext/pdo_dblib
$ phpize
$ ./configure --with-php-config=/usr/local/php/bin/php-config --with-mssql=/usr/local/freetds --enable-pdo --with-pdo-dblib=/usr /local/freetds

如configure出現下列錯誤請按如下方法解決
configure: error: Directory /usr/local/freetds is not a FreeTDS installation directory
就是php找不到freetds的安裝路徑
其實是PHP檢測其安裝目錄的時候有些問題,檢查依據是兩個已經不用的文件,創建兩個空文件就OK
touch /usr/local/freetds/include/tds.h
touch /usr/local/freetds/lib/libtds.a

修改php.ini文件,添加行
extension=pdo_dblib.so

$ cp /usr/local/php-5.3.3/src/ext/pdo_dblib/modules/pdo_dblib.so /usr/lib/php/modules/.
$ /opt/httpd/bin/httpd -k restart
6、整合apache 與php
# vi /opt/httpd/conf/httpd.conf
在最後一行加上:
AddType application/x-httpd-php .php

查找:(設置WEB 默認文件)
DirectoryIndex index.html
替換為:
DirectoryIndex index.php index.html index.htm //在WEB 目錄不到默認文件,httpd 就會執行/var/www/error/noindex.html




Q & A:
Q:
I have the following very simple script that uses PDO/FreeTDS to connect
to a mssql server. I have PHP Version 5.3.3 running on Linux under
Apache. When I view this script via apache/firefox I get proper output.

If I try and run this via the command line, I get
an error connecting to the DB:
SQLSTATE[HY000] Unable to connect: Adaptive
Server is unavailable or does not exist (severity 9).
A:
This is because php-cli is parsing different php.ini.
Please solved this problem as below:
1)Checking the output of phpinfo() of php.ini by execute
$ php -i | grep php.ini
you will get the information of /path_difference/to/php_ini_root/php.ini.
$ cd /path_difference/to/php_ini_root && ln -s /path/to/real/php.ini php.ini

2010年12月8日 星期三

Setting-Up Phing Manual (Non-Pear)

If you are not using the PEAR installer, you will need to setup your environment in order to run Phing. The distribution of Phing consists of three directories: bin , docs and classes. Only the bin, classes and etc directories are required to run Phing. To install Phing, choose a directory and uncompress the distribution file in that directory (you may already have done this in a prior step). This directory will be known as PHING_HOME .

On earlier Windows installations, the script used to launch Phing will have problems if PHING_HOME is a long filepath. This is due to limitations in the OS's handling of the "for" batch-file statement. It is recommended, therefore, that Phing be installed in a short path, such as C:\opt\phing.

Before you can run Phing there is some additional set up you will need to do perform:

Add the full path to the bin/ directory to your path.
Set the PHING_HOME environment variable to the directory where you installed Phing. On some operating systems the Phing wrapper scripts can guess PHING_HOME (Unix dialects and Windows). However, it is better to not rely on this behavior.
Set the PHP_COMMAND environment variable to where your Php binary is located (including the binary i.e. PHP_COMMAND=/usr/bin/php).
Set the PHP_CLASSPATH environment variable (see the section below). This should be set at least point to PHING_HOME/classes. Alternatively, you can also just add the phing/classes directory to your PHP include_path ini setting.
Check your php.ini file to make sure that you have the following settings:
max_execution_time = 0 // unlimited execution time
memory_limit = 32M // you may need more memory depending on size of your build files
If you are using Phing in conjunction with another application, you may need to add additional paths to PHP_CLASSPATH.

Unix

Assuming you are running a Unix dialect operating system with the bash bourne shell and Phing is installed in /opt/phing . The following sets up the environment properly:

export PHP_COMMAND=/usr/bin/php
export PHING_HOME=/opt/phing
export PHP_CLASSPATH=${PHING_HOME}/classes
export PATH=${PATH}:${PHING_HOME}/bin
Windows

On the Windows platfrom, assuming Phing is installed in c:\opt\phing. The following sets up your environment:

set PHP_COMMAND=c:\opt\php\php.exe
set PHING_HOME=c:\opt\phing
set PHP_CLASSPATH=c:\opt\phing\classes
set PATH=%PATH%;%PHING_HOME%\bin


reference : http://phing.info/docs/guide/stable/chapters/Setup.html

2010年12月2日 星期四

XAMPP restrict access to phpMyAdmin by authentication

Wondering how authentication/log-in form will be implemented in xampp? This edit in config.inc.php will handle the job.

The path for the configuration script is \phpMyAdmin\config.inc.php.

This line configures the authentication used by phpMyAdmin in accessing it:

$cfg['Servers'][$i]['auth_type'] = 'authentication method here'; // Authentication method (config, http or cookie based)?
Note:

If you replace the use authentication method here with:

config
- it will use the password and username from the configuration file. Remember the last tutorial? (read it here)

http
- will use the http authentication of Apache(secure/recommended settings)

cookie
- will use the database for username in authentication and will require browsers to allow cookie. (secure/recommended setting)

wibiya widget