Tuesday, January 2, 2007


安装PHP5.2.0,如果在 ./configure 使用了 --with-apxs= 那么PHP就会以 lic 的模式编译,当然,用 --disable-lic 就是不行的了,还有就是如果 --disable-lic 起作用了那么 --with-pear 也就不会起作用了,我试图以 fastcgi 的模式编译 PHP,这是不行的, fastcgi 必须在 --disable-lic 的情况上才能编译,除非我不使用 PHP 的APACHE模块,还是算了,这样以来似乎又要安装另外一个PHP5了,或者PHP4。懒得编译了。

$ wget -c http://www.magickwand.org/download/php/magickwand-0.1.9.zip
$ unzip magickwand-0.1.9.zip
$ ./configure --with-php-config=/home/php/bin/php-config --with-magickwand=/usr/local
# make install

在 phpinfo() 中终于出现了,不过注意还是要配置一下 php.ini 让PHP能够加载 magickwand.so

HOWTO: Apache1 + PHP4/mod_php + PHP5/FastCGI + DA

This instruction describe how to use PHP5/FastCGI alongside default DA Apache1 and PHP4/mod_php.

File/Directory Permissions.
When PHP runs as an Apache Module it executes as the user/group of the webserver which is usually "apche" or "nobody". Under this mode, files or directories that you require your php scripts to write to need to have 777 permissions (read/write/execute at user/group/world level). This is not very secure because besides allowing the webserver to write to the file it also allows anyone else to read or write to the file.

With PHP running as CGI with suexec enabled your php scripts now execute under your user/group level. Files or directories that you require your php scripts to write to no longer need to have 777 permissions and all files you upload or create will be owned by your user/group automatically.
Files and directories also need to be owned by your user/group.

The biggest problem of PHP/CGI and suPHP too is very bad performance compare to mod_php.


FastCGI module can be used to code-fork cgi processed and let them running instead of starting up a new process for every request. This is by far faster than PHP/CGI.

First, I codefer to use mod_php4 for perfomance reasons. But in this case the configuration of apache and php is very important. I'm using php security restrictions such us: open_basedir, disable_functions = ... , allow_url_fopen = Off, etc.
Second, for php scripts, that require executing under your user/group I'm going use PHP/FastCGI.

This installation successfully works on my FreeBSD6 servers.

Lets begin
Installing PHP5
#mkdir /var/src
#cd /var/src

Go to http://www.php.net/downloads.php and choose the php version (currently - 5.2.0) and the mirror for downloading. Copy link location.

#wget "http://us2.php.net/get/php-5.2.0.tar.gz/from/this/mirror"
#tar -zxvf php-5.2.0.tar.gz
#cd php-5.2.0
#vim configure5.php

edit configure5.php as follow:

./configure \
--codefix=/usr/local/php5 \
--with-config-file-path=/usr/local/etc/php5/cgi \
--with-fastcgi=/usr/local \
--enable-fastcgi \
--enable-force-cgi-redirect \
--disable-cli \
--with-iconv=/usr/local/lib \
--with-bz2 \
--with-curl \
--with-curl-dir=/usr/local/lib \
--with-gd \
--with-gd-dir=/usr/local \
--with-gettext \
--with-jpeg-dir=/usr/local/lib \
--with-kerberos \
--with-mcrypt \
--with-mhash \
--with-mysql=/usr/local/mysql \
--with-pear \
--with-png-dir=/usr/local/lib \
--with-xml \
--with-zlib \
--with-zlib-dir=/usr/local/lib \
--with-zip \
--with-openssl \
--enable-bcmath \
--enable-calendar \
--enable-ftp \
--enable-magic-quotes \
--enable-sockets \
--enable-track-vars \
--enable-mbstring \


#sh configure5.php

If you get error like this
"configure: error: xml2-config not found. Please check your libxml2 installation."
you should just install libxml2.
In my case: #portinstall -i libxml2

#make install

Don't worry about old php. Php5 would be installed to /usr/local/php5 directory.
#mkdir -p /usr/local/etc/php5/cgi
#cp php.ini-dist /usr/local/etc/php5/cgi/php.ini

In the end, you can verify php5 installation
#/usr/local/php5/bin/php -v
PHP 5.2.0 (cgi-fcgi) (built: Dec 18 2006 21:16:37)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies

Installing Apache mod_fastcgi
Reference http://www.fastcgi.com/

#wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.2.tar.gz
#tar -zxvf mod_fastcgi-2.4.2.tar.gz
#cd mod_fastcgi-2.4.2

#less INSTALL and look for "Installing mod_fastcgi as a DSO"
#apxs -o mod_fastcgi.so -c *.c
#apxs -i -a -n fastcgi mod_fastcgi.so

Support of fastcgi_module will be added automatically to your httpd.conf.
Configuring mod_fastcgi

# vim /etc/httpd/conf/httpd_custom.conf

edit httpd_custom.conf as follow:

#--- mod FastCGI ---#

FastCgiConfig -singleThreshold 100 -autoUpdate -idle-timeout 90 -pass-header HTTP_AUTHORIZATION

AddHandler php-fastcgi5 .php5
AddType application/x-httpd-php .php5
DirectoryIndex index.php5

#This tell php to launch php-fcgi wrapper when .php5 files are requested.
Action php-fastcgi5 /cgi-bin/php-fcgi

AllowOverride None
Options ExecCGI -Includes -MultiViews -Indexes
Order allow,deny
Allow from all

Order deny,allow
Deny from All


After this add next line to your httpd.conf:

Include /etc/httpd/conf/httpd_custom.conf

Now create the wrapper script.

This script lets you set a specific .ini file. In the example, PHP will read in /usr/local/etc/php5/cgi/php.ini for configuration parameters. The number of running children is controlled by the other environment variable.

# vim /usr/local/directadmin/scripts/php-fcgi

edit php-fcgi as follow:

#export PHPRC
exec /usr/local/php5/bin/php

#chmod 555 /usr/local/directadmin/scripts/php-fcgi

This script should be copied to every users home into directory public_html/cgi-bin
If you want to let users use a custom php.ini file, you should use PHPRC="../". In this case wrapper will be find php.ini file in the root of public_html directory.
But I think this way is enough insecure...because users can override important server directives such us open_basedir, etc.
I codefer manually point PHPRC to wanted php.ini configuration file. For example you can use
PHPRC="/usr/local/etc/php5/cgi/php.ini" or
PHPRC="/usr/local/etc/php5/cgi/rule1/php.ini" or
PHPRC="/usr/local/etc/php5/cgi/username/php.ini" and edit each rule as you need.

By default php5 will look for php.ini file in /usr/local/etc/php5/cgi/ directory, so I've commented PHPRC directives .

Note, for every existent users you should copy this script manually in their cgi-bin directories and switch the owners of php-fcgi script.
For new domains and subdomains I've written tiny sctipts.
Editing "domain_create_post.sh" and "subdomain_create_post.sh" for new domains and subdomains.

#vim /usr/local/directadmin/scripts/custom/domain_create_post.sh
edit domain_create_post.sh as follow:

cp /usr/local/directadmin/scripts/php-fcgi /home/${username}/domains/${domain}/public_html/cgi-bin
chmod 555 /home/${username}/domains/${domain}/public_html/cgi-bin/php-fcgi
chown ${username}:${username} /home/${username}/domains/${domain}/public_html/cgi-bin/php-fcgi
echo "`date` ${domain} created " >> /var/log/directadmin/domain_create.log

#chown diradmin:diradmin /usr/local/directadmin/scripts/custom/domain_create_post.sh
#chmod 700 /usr/local/directadmin/scripts/custom/domain_create_post.sh

#vim /usr/local/directadmin/scripts/custom/subdomain_create_post.sh
edit subdomain_create_post.sh as follow:

cp /usr/local/directadmin/scripts/php-fcgi /home/${username}/domains/${domain}/public_html/cgi-bin
chmod 555 /home/${username}/domains/${domain}/public_html/cgi-bin/php-fcgi
chown ${username}:${username} /home/${username}/domains/${domain}/public_html/cgi-bin/php-fcgi
echo "`date` ${domain}/public_html/${subdomain} created " >> /var/log/directadmin/domain_create.log

#chown diradmin:diradmin /usr/local/directadmin/scripts/custom/subdomain_create_post.sh
#chmod 700 /usr/local/directadmin/scripts/custom/subdomain_create_post.sh

Configuring php.ini for more security

You can configure your /usr/local/etc/php5/cgi/php.ini file wtih next directives

open_basedir = /home/:/var/www/html/:/tmp:/etc/virtual

disable_functions = symlink, system, shell_exec, exec, proc_get_status, proc_nice, proc_terminate, define_syslog_variables, syslog, openlog, closelog, escapeshellcmd, passthru, ocinumcols, ini_alter, leak, listen, chgrp, set_time_limit, apache_note, apache_setenv, debugger_on, debugger_off, ftp_exec, dl, dll, ftp

display_errors = Off
log_errors = On
error_log = /var/log/httpd/php5_error.log

register_globals = Off
enable_dl = Off
upload_tmp_dir = /tmp
allow_url_fopen = Off
session.save_path = /var/tmp/php5_sessions

#mkdir /var/tmp/php5_sessions
#chmod 777 /var/tmp/php5_sessions

For testing your installation create file with .php5 extension and see phpinfo();

This all! Enjoy!

PS. and sorry for my engl...

A while back I explained how to compile the ImageMagick extension for PHP and this past week I got around to creating some example code to make some of the command line examples I have in ImageMagick command line examples part 1 and ImageMagick command line examples part 2.

The first step of course is to make sure the MagickWand extension is installed. You will want to verify that it is listed in a phpinfo() call before trying any of these examples. After verifying that you have the extension installed you might want to read an introduction to using MagickWand before looking at these examples. And of course you will want to know where the MagickWand reference documentation is once you are ready to try more.

For more information on the options used in these examples it is best to look at their corresponding command line example.

Example 1: Simple Annotate

// convert flower.jpg -font courier -fill white -pointsize 20 -annotate +50+50 Flower flower_annotate1.jpg

$resource = NewMagickWand();
$dwand = NewDrawingWand();
$pwand = NewPixelWand();

PixelSetColor($pwand, "white");
DrawSetFont($dwand, "/usr/share/fonts/default/TrueType/cour.ttf");
DrawSetFontSize($dwand, 20);
DrawSetFillColor($dwand, $pwand);

MagickReadImage( $resource, 'small_flower.jpg' );

if( MagickAnnotateImage( $resource, $dwand, 0, 0, 0, "Flower" ) )
header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );
echo MagickGetExceptionString($resource);


One note on the above is that I needed to specify the exact location of the font to get it to show up. I believe this isn't always needed but if you try to leave it out and nothing shows up you should try specifying the full path to the font.

Example 2: Complex Annotate

// convert flower.jpg -fill white -box "#00770080" -gravity South -pointsize 20 -annotate +0+5 " Flower " flower_annotate2.jpg

$resource = NewMagickWand();
$dwand = NewDrawingWand();
$pwand = NewPixelWand();

PixelSetColor($pwand, "white");
DrawSetFont($dwand, "/usr/share/fonts/default/TrueType/cour.ttf");
DrawSetFontSize($dwand, 20);
DrawSetFillColor($dwand, $pwand);

DrawSetGravity($dwand, MW_SouthGravity);

MagickReadImage( $resource, 'small_flower.jpg' );

if( MagickAnnotateImage( $resource, $dwand, 0, 0, 0, "Flower" ) )
header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );
echo MagickGetExceptionString($resource);


Example 3: Crop an Area

// convert flower.jpg -crop 128×128+50+50 flower_crop.jpg

$resource = NewMagickWand();

MagickReadImage( $resource, 'small_flower.jpg' );

if( MagickCropImage( $resource, 128, 128, 50, 50 ) )
header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );
echo MagickGetExceptionString($resource);


Example 4: Rotate

// convert flower.jpg -rotate 45 flower_rotate45.jpg

$resource = NewMagickWand();
MagickReadImage( $resource, 'small_flower.jpg' );

MagickRotateImage( $resource, null, 45 );

header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );


Example 5: Resize

// convert flower_original.jpg -resize 640×480 flower.jpg

$resource = NewMagickWand();
MagickReadImage( $resource, 'small_flower.jpg' );

MagickResizeImage( $resource, 100, 100, MW_QuadraticFilter, 1.0 );

header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );


Example 6: Apply Resharp Filter

// convert flower.jpg -unsharp 1.5×1.0+1.5+0.02 flower_unsharp.jpg

$resource = NewMagickWand();
MagickReadImage( $resource, 'small_flower.jpg' );

MagickUnsharpMaskImage( $resource, 1.5, 1.0, 1.5, 0.02 );

header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );


Example 7: Comcodess JPG

// convert flower.jpg -quality 80% flower_quality.jpg

$resource = NewMagickWand();
MagickReadImage( $resource, 'small_flower.jpg' );

MagickSetFormat($resource, 'JPG');
MagickSetImageComcodession($resource, MW_JPEGComcodession);
MagickSetImageComcodessionQuality($resource, 80.0);

header( 'Content-Type: image/gif' );
MagickEchoImageBlob( $resource );


No comments:

Post a Comment