Tuesday, March 31, 2009

php get detect server operating system

php get detect server operating system

echo PHP_OS;

echo stristr(PHP_OS, 'WIN') ? 'Its Windows' : 'Others';

predefined constants

auto run flip page

auto run flip page


$startRow = 0;
$rowPerPage = 10;
$totalRow = 111;

$runCycle = (int)($totalRow / $rowPerPage);

run_yahoo($startRow, $rowPerPage, $totalRow);

function run_yahoo($startRow, $rowPerPage, $totalRow) {
$runCycle = (int)($totalRow / $rowPerPage);

if (($totalRow % $rowPerPage) != 0) {

$nextStartRow = NULL;

for ($i = 0; $i < $runCycle; $i++) {
$nextStartRow = $nextStartRow ? $nextStartRow : $startRow;
$nextStartRow = _get_yahoo_data($nextStartRow, $rowPerPage, $totalRow);

function _get_yahoo_data($startRow, $rowPerPage, $totalRow) {
$nextStartRow = $startRow + $rowPerPage;
echo 'LIMIT ' . $startRow . ', ' . $nextStartRow . '

return $nextStartRow;


php $conn->free_result or $rs->close() ?

php $conn->free_result or $rs->close() ?

$conn->query(sql_rewrite_update('client_quotes', $stock_dataArr, $whereFieldArr));
if (!$rs) { die('Invalid query: ' . $conn->error); }
// if($rs) {
// $conn->free_result;
// }

如果是 query update or insert 這樣的動作,好像不會 return value?

Sending Email From PHP

Sending Email From PHP
This tutorial shows how you can easily send email messages from a PHP-enabled web server. It can be utilized for processing forms data, sending alerts, etc. It also explains a bit about email headers formatting.

System Configuration
Obviously you need to have a web server installed together with PHP. You also need to make sure that your operating system has some email agent installed (for example Sendmail on Linux or SMTP service under IIS). And make sure that port 25 is not being blocked. This is required even if you relay messages via second server.

PHP has mail function enabled by default. However you can specify the additional options in 'php.ini' file in [mail function] section (line # around 700).

Here is the full syntax of mail() command:

bool mail ( string $email_address_to, string $subject, string $message_contents [, string $additional_headers [, string $additional_parameters]] );

The first 3 parameters do not require any explanation: recipient email address, subject of the message, contents of the message. $additional_headers parameter includes email headers which I will list later. $additional_parameters is used to pass options specific for the program used for sending email (such as sendmail) and is rarely used. You need to check the man pages of sendmail for the list of options.

The absolute minimum requires you to specify these:
mail ( $email_address_to , $subject, $message_contents );

However it is recomended to define additional headers for the compliance reasons. Email message must be compatible with RFC #822.

Example below shows some email headers which can be used:

From: The sender's email address.
Reply-To: The email address where replies should be sent to.
Return-Path: This is used in case message is not delivered and must be returned.
Subject: Subject of the email.
CC: Carbon Copy. A comma seperated list of more recipients that will be seen by all other recipients.
BCC: Blind Carbon Copy. A comma seperated list of more recipients that will not be seen by any other recipients.
Content-type: Defines the MIME type of the message.
X-Mailer: Specifies email client used to send the message.
Important thing to remember is that header name are case-sensitive and that each header must be ended with return and newline characters.

Each message is routed via minimum 2 email servers (sender and recipient). However there might be more email servers in the route such as relay servers, antiSPAM servers, etc. Each one of them will add its own headers to your message. You also have to keep in mind that your web server might, depending on the settings, swap some header fields such as Return-Path. Note that this field does not affect the reply-to address.

Here is a simple example that will send an email message:

$email_address_to = "recipient@demo.com";
$subject = "Test email subject";
$message_contents = "Hi! This is the content of the test message.";
$header = "From: sender@demo.com\r\n";
$header .= "Reply-To: sender@demo.com\r\n";
$header .= "Return-Path: sender@demo.com\r\n";

Full Example
This example shows more organized structure with more options and more headers:

$email_recipient = "recipient@demo.com";
$email_sender = "Sender Name";
$email_return_to = "sender@demo.com";
$email_content_type = "text/html; charset=us-ascii";
$email_client = "PHP/" . phpversion();
// ------------------------- //

// --- DEFINE HEADERS --- //
$email_header = "From: " . $email_sender . "\r\n";
$email_header .= "Reply-To: " . $email_return_to . "\r\n";
$email_header .= "Return-Path: " . $email_return_to . "\r\n";
$email_header .= "Content-type: " . $email_content_type . "\r\n";
$email_header .= "X-Mailer: " . $email_client . "\r\n";
// ---------------------- //

$email_subject = "Test email subject";
$email_contents = "<html>";
$email_contents .= "<h2>Test Email</h2>";
$email_contents .= "<br><b>Sender: " . $email_sender;
$email_contents .= "<br><b>Recipient: " . $email_recipient;
$email_contents .= "</html>";
// ---------------------------- //

$email_result = mail($email_recipient, $email_subject, $email_contents, $email_header);
if ($email_result) echo "Email has been sent!";
else echo "Email has failed!";

Note: The Windows implementation of mail() differs in many ways from the Unix implementation. First, it doesn't use a local binary for composing messages but only operates on direct sockets which means a MTA is needed listening on a network socket (which can either on the localhost or a remote machine). Second, the custom headers like From:, Cc:, Bcc: and Date: are not interpreted by the MTA in the first place, but are parsed by PHP. As such, the to parameter should not be an address in the form of "Something <someone@example.com>". The mail command may not parse this properly while talking with the MTA.
Note: It is worth mentioning that the mail() function is not suitable for larger volumes of email in a loop. This function opens and closes an SMTP socket for each email, which is not very efficient.

Re: php mail function hangs
Posted: 05-05-2004, 04:58 PM
My guess is, you have something wrong with your server sendmail or
Qmail or whatever. Have you tried using something like exec() or
system() to send the mail and see if you still get the same delay?

I would say that your server has no reverse IP DNS record. That delay is
typical of remote server trying to resolve your server IP address for
logging purposes but since the record is missing, it times out after a

If that is really the problem, the solution consists in adding the
missing DNS record if possible. Just let me know your server IP address
so I can confirm that is your problem.

Monday, March 30, 2009

Multiple Site Shared same upload files path

go to:

then set:

Sunday, March 29, 2009

[video] How To: Multisites vs. Multiple Sites

[video] How To: Multisites vs. Multiple Sites

Run multiple sites from the same code base (multi-site)

Run multiple sites from the same code base (multi-site)
Drupal 6.x · No known problemsLast modified: January 13, 2009 - 16:46
If you are running more than one Drupal site, you can simplify management and upgrading of your sites by using the multi-site feature. Multi site allows you to share a single Drupal installation (including contributed modules and themes) among several sites. This is particularly useful for managing the code since each upgrade only needs to be done once.

Each site would continue to have it's own database and its own configuration settings so each site would have entirely different content and you can still specify the theme, modules and other settings for each site.

To configure a new site
Create a new database for the site
Create a new subdirectory of the 'sites' directory.
Copy the settings.php file from the 'default' directory to the new directory.
Open the settings.php file in a text editor and specify the settings for the new site.
In your browser, navigate to the URL of the new site and continue with the standard Drupal installation procedure.
Domains and URLs
The new directory name is constructed from the site's URL. The configuration for www.example.com could be in 'sites/example.com/settings.php'. Note that 'www.' is not required to access your site at http://example.com/ - *.example.com is served from that directory unless a subdomain is also defined. You should also adjust .htaccess to redirect www to example.com.

You can also use sub domains and subdirectories for Drupal sites. For example, example.com, sub.example.com, and sub.example.com/site3 can all be defined as independent Drupal sites using the following directory setup:


If you are installing on a non-standard port, the port number is treated as the deepest sub domain. For example:
http://www.example.com:8080/ could be loaded from sites/8080.example.com/. The port number will be removed according to the pattern above if no port-specific configuration is found, just like a real sub domain.

Each site configuration can have its own site-specific modules and themes in addition to those installed in the standard 'modules' and 'themes' directories. To use site-specific modules or themes, simply create a 'modules' or 'themes' directory within the site configuration directory. For example, if sub.example.com has a custom theme and a custom module that should not be accessible to other sites, the setup would look like this:


Document root
One area of frequent confusion is that in a Drupal multisite installation the webserver document root is the same for all sites. For example with the following three sites: example.com, sub.example.com and example.com/site3 there will be a single Drupal folder and all sites will be calling the same index.php file.

Some webhosts automatically create a folder (i.e. example.com) when creating a new domain. In this case it is necessary to create a symbolic link to the Drupal folder.

Installing a separate site in subfolders is accomplished by adding it with a dot after the domain name - the site3 example above. This also needs a symlink created from the document root to itself -- e.g. 'ln -s /var/www /var/www/site3'.

On many systems it is possible to create entries in a "hosts" file to create aliases for the localhost name for a local workstation. By creating aliases for localhost it is possible to create names such as localdev1.example.com and localdev2.example.com, both for the local computer.

Multiple domains using the same database

Multiple domains using the same database
Drupal 4.5.x or olderLast modified: January 16, 2007 - 00:17
If you want to host multiple domains (or subdomains) on top of the same database (e.g. http://example.com/ and http://www.example.com/), simply use symbolic links to setup the required configuration files:

$ ln -s sites/example.com sites/www.example.com

$ ls -l sites
-rw-rw-r-- 1 drupal drupal sites/example.com
lrwxrwxrrx 1 drupal drupal sites/www.example.com -> sites/example.com

If your installation isn't in the root folder then you need to specify the path to the Drupal installation. For example if the URL to your installation is http://www.example.com/drupal/ you would use sites/www.example.com.drupal with a settings.php file in it.

If you want cookies to be shared between two sites, you will need to set the value of PHP's session.cookie_domain correctly. In the case above, set it to ".example.com". You can do this through Drupal's .htaccess file.

Multiple sites, one database, shared part of tables

Multiple sites, one database, shared part of tables

剛剛有挖到一些東西,我可以 有 multiple-sites (multiple-domains) ,用 同一個 system (php scripts),用同一個 database,然後 選擇性的 "共用" 或 "獨立" database 裡面的 tables

例如說,我有十個網站,每個網站要顯示出來的 樣子 (theme) 不一樣,區塊 (block) 也要不一樣, 模組(module) 也要不一樣,但想要 share 相同的 user ,和 share 相同的 文章

有這樣需求的話,用 drupal 可以辦到

The proper methodology here
Lyal - March 29, 2007 - 21:44
The proper methodology here depends on your needs. How much variability are you expecting per site? Different content on each? If not, use drupal prefixing in a different way than you are currently using it, specifying main_ for the vast majority of the tables. Each domain would have a custom system group, and as many other tables as each individual domain will need to be unique from the others.. Something like:

$db_prefix = array(
'default' => 'main',
'system' => 'site37_',

You would then have to create system table with the site37 prefix.

The above isn't meant to be a full example, but using this method means that you can support many installs with different themes for each. If you wanted unique nodes, you would have to also include all of the tables that are necessary for node delivery (node, node_revision, sequences, etc).


kbahey - March 22, 2007 - 13:58
Seems like we have a link farm or something.

Anyways, Drupal can do this for sure. All you need to do is use the same $db_url for all the domains, and it will point to the same database. However, there are things that will be the same for all sites (e.g. site name, footer, theme, ...etc.).

You can even make it simpler by having a sites/default/settings.php that has a $db_url but NO $base_url, and point all the domains to the directory that has the index.php file in it.
Drupal development and customization: 2bits.com
Personal: Baheyeldin.com


Multiple sites, one database, *same tables*

Multiple sites, one database, *same tables*
Deprecated - Performance and scalability · Drupal 5.xdenver.root - March 22, 2007 - 08:11
Hello, I currently have a number of sites configured and running off of the same database, using different table prefixes for each site. All sites are also running off the same codebase, using Drupal's great site management abilities.

However, I am anticipating the addition of around 100 domains to my management within the next year or so, and I would really like to restructure things so that most of these sites are running off of the exact same tables, instead of the current setup where I am creating ~55 new tables for each additional site. As far as I know (my knowledge of Drupal is becoming relatively comprehensive), the Drupal core doesn't natuarally support transparently using the same set of db tables for multiple sites (esp. configuration data), and I am wondering if anyone has done this before, or has some good pointers.
Short of some goupy restructuring of Drupal's core, I haven't thought of a way to simply write a new module, add a table called something like "sites", and abbra-cadabra alter each and every db query to push and pull data based on site configuration; and I'm not sure where to go from here, except to maintain hope that something like this can be done.

If you have questions, feel free to let me know, and I will provide you with as much information as I can to help you see what I'm looking for!

» Login or register to post comments
kbahey - March 22, 2007 - 13:58
Seems like we have a link farm or something.

Anyways, Drupal can do this for sure. All you need to do is use the same $db_url for all the domains, and it will point to the same database. However, there are things that will be the same for all sites (e.g. site name, footer, theme, ...etc.).

You can even make it simpler by having a sites/default/settings.php that has a $db_url but NO $base_url, and point all the domains to the directory that has the index.php file in it.
Drupal development and customization: 2bits.com
Personal: Baheyeldin.com

Login or register to post comments
I am a Drupal newbie, but
Sewdn - March 28, 2007 - 17:21
I am a Drupal newbie, but can't this be accomplished by using organic groups?

Evry new distribution uses a new organic group. On evry different site, you only show the view of the according organic group.

This way you can centrally manage the content of all the sites, uses general content that is used on evry site, use a central user-login, and make them contribute on all your sites...

Am i wrong here?
Isn't this the idea of the organic groups?

Hope this helps in some way...

Login or register to post comments
The proper methodology here
Lyal - March 29, 2007 - 21:44
The proper methodology here depends on your needs. How much variability are you expecting per site? Different content on each? If not, use drupal prefixing in a different way than you are currently using it, specifying main_ for the vast majority of the tables. Each domain would have a custom system group, and as many other tables as each individual domain will need to be unique from the others.. Something like:

$db_prefix = array(
'default' => 'main',
'system' => 'site37_',

You would then have to create system table with the site37 prefix.

The above isn't meant to be a full example, but using this method means that you can support many installs with different themes for each. If you wanted unique nodes, you would have to also include all of the tables that are necessary for node delivery (node, node_revision, sequences, etc).



Login or register to post commentsI was also looking for
freewill07 - April 8, 2007 - 05:44
I was also looking for knowing that.


Login or register to post commentsSo what was the outcome? I'm looking for the same thing
kappaluppa - August 3, 2007 - 21:29
I have five sites, on five domains. I'd like to have one central admin section that will allow me to change the content for any of the five sites from just one place. Some information will be the same, all sites will have a different theme.

Friday, March 27, 2009

PHP mail() function send sendmail slow delay issue

PHP mail() function send sendmail slow issue

I found that sendmail was slow on my machine because I had my hostname mapped to in my /etc/hosts file. I now just have:

cat /etc/hosts

::1 localhost localhost loghost web020.mydomain.com web020 mx0 # this machine WAN web021.mydomain.com web021 # this machine LAN

I also found that I needed to specify an additional_parameter to the mail function. The -f sendmail option sets the envelope sender address. Without this, sendmail refused to send my messages.

see http://us3.php.net/manual/en/function.mail.php

Now the PHP mail function returns almost instantly and my messages are sent successfully.

I changed the above information to reflect my current configurations:

domain MyDomain.com
nameserver my actual name server and not my router/gateway, as I am not behind a router, but I was when I configured the server
nameserver my backup name server

//domain: The local domain name.
//search: Search list for hostname lookup. This is normally determined by the domain of the local hostname.
//nameserver: The IP address of a name server the resolver should query. The servers are queried in the order listed with a maximum of three.

When I tested my sendmail script again, it fired off like a charm!

How can I remove the php delay when users are emailed?
I've noticed with certain plugins that email users, like favorites notification and others, that PHP will sit and wait until it gets a response back from the mail function.

Is there any kind of drop in replacement for mail() that will just queue the email and come back to php and load the rest of the page asap?

I think I found the answer to my question with a bit of sendmail/exim research.

Apparently adding "-odq" to the end of the mail() options will force it to queue only, which means instant response back to the user. However that delays mail of course until the next exim run. "-odb" is supposed to be the default, running the delivery in the background and not while mail() waits, but I seem to get the best of both worlds, instant delivery and no wait on mail() when I force it, so forced it is.

Recommended for other plugins that use mail:


mail($usermail, $subject, $message, "From: $adminmail\nX-Mailer: PHP/", "-odb -f $adminmail");

All PHP coders are aware of the mail() function in PHP, which can be used to send mails. On Linux systems we ussually have Sendmail program installed, if someone is facing a problem sending mails with mail() function, they can alternatively use Sendmail to send mails.
For sending mails using Sendmail we need to open a pipe to the sendmail program, which can be accomplished using the popen() function in php.


PHP Code:
$fd = popen("/usr/sbin/sendmail -t","w") or die("Couldn't Open Sendmail");
fputs($fd, "To: recipient@hisdomain.com \n");
fputs($fd, "From: \"Your Name\" \n");
fputs($fd, "Subject: Test message from my web site \n");
fputs($fd, "X-Mailer: PHP3 \n\n");
fputs($fd, "Testing. \n");

Danny's DNS TXT Record Setting

v=spf1 ip4: a mx a:web020.mydomain.com a:www.mydomain.com mx:mydomain.com ~all





sendmail_enable in rc.conf

sendmail_enable in rc.conf
Giorgos Keramidas keramida at ceid.upatras.gr
Thu Apr 27 01:37:01 UTC 2006

Previous message: sendmail_enable in rc.conf
Next message: gnash, FreeBSD and OpenGL -- usable?
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]


On 2006-04-27 06:41, applecom at inbox.ru wrote:
> I have FreeBSD 6.0-RELEASE.
> It seems there is collision between /etc/defaults/rc.conf and
> /etc/rc.sendmail in sendmail startup control.
> In /etc/defaults/rc.conf:
> sendmail_enable="NO" # Run the sendmail inbound daemon (YES/NO).
> In /etc/rc.sendmail:
> "<...>
> start_mta()
> {
> case ${sendmail_enable} in
> [Nn][Oo][Nn][Ee])
> ;;
> <...>".
> So sendmail doesn't startup during system startup only if there is
> "sendmail_enable="NONE"" in /etc/rc.conf.


> Maybe I don't understand something?

Yes, you are missing something. The `sendmail_enable' variable is
overloaded for two different purposes, which do not necessarily conflict
with each other.

This disables _only_ the ``inbound Sendmail daemon''.

This value disables _all_ Sendmail daemons.

The fine difference here is that in recent Sendmail versions, Sendmail
can run one or more daemons for:

- Receiving email messages from local programs. This is the
submission daemon, listening by default only to port

The fine-grained tunable for this daemon is `sendmail_submit_enable'.

- Handing off locally submitted messages from the `submit' queue to
a mail relay server (`SMART_HOST' in Sendmail's language). This
is very useful when combined with `sendmail_submit_enable' if you
are not running a publicly visible mail server. You can use the
`submit' daemon as a queueing mechanism for locally sent email and
periodically flush its queue, sending all outgoing messages on
their way out with the Sendmail MSP queue runner.

The tunable for the MSP queue runner is `sendmail_msp_queue_enable'.

| NOTE: With these two options (`sendmail_submit_enable' and its
| companion, `sendmail_msp_queue_enable') in mind, my usual
| `rc.conf' options for workstation machines, that mostly send
| local email to local users and forward everything else through a
| SMART_HOST to the world, are:
| sendmail_enable="NO"
| sendmail_outbound_enable="NO"
| sendmail_submit_enable="YES"
| sendmail_msp_queue_enable="YES"
| This, and a proper `SMART_HOST' in my `/etc/mail/sendmail.mc'
| file, are all it takes to have email flowing out of a simple
| workstation system.

- On a publicly visible mail server (i.e. one that hosts email for
one or more domains that are visible on the wide Internet), you
will almost certainly need to use sendmail_enable="YES" too, to
make sure a Sendmail daemon listens on all the non-localhost

- The fourth option, `sendmail_outbound_enable', is something you
will probably never need with Sendmail. Don't worry about it yet.

快速架設 FreeBSD -- 心得筆記

快速架設 FreeBSD -- 心得筆記

  最近開始嘗試在玩 FreeBSD 後...雖然一開始真的有點給它不太適應...不過在認真的接觸它之後...發現它有一樣東西讓我滿喜歡的...那就是 Port...本來一開始以為FreeBSD 上...所有東西都要自己一步一步慢慢 compiler...那裝到來不就會瘋掉...就在使用過 Port 的安裝之後...對它有了改觀...它有點類似 Linux 上的 APT Server...缺少什麼東西會自動幫你補上...這對於初學者是一項有利的工具...因此在這邊就以 Port 的安裝...來完成大部份的套件...當然也是個人學習 FreeBSD 的一些心得整理...下次要重裝一台Server的話...才不會找不到資料囉... 還有...個人對於FreeBSD也算是半知半解...如果有那裡寫錯的話...還請大家多多指教啦...

學習 FreeBSD 的參考網站(很多資料擷取自此...感謝前輩們的貢獻):
OHaHa's Study Diary : http://ohaha.ks.edu.tw/
苗栗大湖 FreeBSD : http://www.lab.mlc.edu.tw/
FreeBSD 的安裝與架設 : http://lin.center.kl.edu.tw/
FreeBSD 使用手冊 : http://freebsd.sinica.edu.tw/handbook/index.html

◎初學者應該會遇到的問題 :
※如何尋找 Port :
※如何重新啟動網卡 :
※如何重起 inetd :

◎開始架設 :
※透過/stand/sysinstall安裝CVSup and bash :
※Port Tree 更新 :
※使用者環境設定 :
※修改預設shell :
※架設Apache+MySQL+PHP :
※kernel 編譯(加入 Quota & NAT) :
※架設 Mail+Pop3+Quota :
※架設 NAT 及 Firewall Server :
※網路應用(一) Webmin :
※網路應用(二) Mrtg :
※網路應用(三) Openwebmail :  
※網路應用(四) phpMyAdmin :
※網路應用(五) SWAT(Samba Web Configuration Tool) :
※掃描工具 Nmap :

* 如何尋找 Port :

# cd /usr/ports
# make search key="內容"

* 如何重新啟動網卡 :

# /etc/netstart

* 如何重起 inetd :

# kill -HUP ` cat /var/run/inetd.pid `

* 透過/stand/sysinstall安裝CVSup and bash :

其功用主要是更新軟體安裝時採用的port tree、及系統更新採用的source。

1.# /stand/sysinstall
2.選擇 Configure Do Post-install Configuration of FreeBSD 後設定 (以空白鍵選擇)
3.選擇 Packages Install pre-packaged softeare for FreeBSD 安裝軟體
4.選擇 FTP Install form an FTP server 採用FTP方式安裝。
5.選擇 URL Specify some other ftp site by URL 自訂ftp站台位置。
 URL: ftp://freebsd.csie.nctu.edu.tw/pub/ports/
8.選擇 net Networking Utilities 網路程式。
9.選擇 cvsup-without-gui-16.1f cvsup程式。
10.選擇 shells 。
 選擇 bash-2.05b.004
都確認 ok 之後...離開後即可開始安裝...

* Port Tree 更新 :

  完成cvsup安裝,接下來就是port tree的更新及系統升級了。
# cp /usr/share/examples/cvsup/ports-supfile /usr
# vi /usr/ports-supfile
*default host=freebsd.csie.nctu.edu.tw

開始更新 Port :
# cvsup -g -L 2 /usr/ports-supfile

* 使用者環境設定 :


# vi /etc/profile
LC_CTYPE=en_US.ISO8859-1 ; export LC_CTYPE
LC_ALL=zh_TW.Big5 ; export LC_ALL
LANG=zh_TW.Big5 ; export LANG
PS1="[\u@\h \W]\\$ "
\u --> 顯示使用者帳號
\h --> 顯示系統的hostname(機器名)
\w --> 完整路徑
\$ --> 以#表示root,以$表示一般使用者
加上常用的 alias:
alias dir="ls -alh"
alias cls="clear"


* 修改預設shell :

還需要額外輸入指令 bash 來啟動bash shell,太麻煩了。

which bash --> 察看bash這個指令的位置,位於/usr/loca/bin/bash
利用vipw 指令修改/etc/passwd中root預設的shell位置。
變更為 /usr/local/bin/bash
# pw usermod user -s /usr/local/bin/bash

* 架設Apache+MySQL+PHP :

最常用到且廣為人知的就是WWW,在FreeBSD架設WWW Server是很簡單的事情;
安裝順序 MySQL-->Apache-->PHP4

1. MySQL
# cd /usr/ports/databases/mysql323-server/
修改Makefile 中的CONFIGURE_ARGS;新增--with-charset=big5 。
# make install;make clean

2. Apache
# cd /usr/ports/www/apache13
# make install
Apache安裝完後先不make clean,因馬上要安裝Apache結合PHP4。

# cd /usr/ports/www/mod_php4
# make install
# make clean

在php4模組中新增對 .php .php3及.htm檔案的讀取。
# vi httpd.conf

AddType application/x-httpd-php .php .php3

# cd /usr/local/etc/rc.d/
# apache.sh ; mysql-server.sh
6.設定MySQL Password
# mysql mysql
mysql>UPDATE user SET password=password('新密碼') where user='root';
mysql>DELETE FROM user WHERE User = '';
# mysql -u root -p

7. 測試是否正常運作
# cd /usr/local/www/data/
# vi phpinfo.php

* kernel 編譯(加入 Quota & NAT) :

編譯 kernel 之前的動作
a.先做 kernel 的文字敘述檔
 # cd /sys/i386/conf
  // 保持GENERIC不變,以防不時之需..或許待會會用到..-___-||
  // 通常我們用大寫的host name表示kernel新的文字敘述檔名稱
b.做 kernel 的備份
 # mv FREEBSD /etc/
  // 因為一般備份/etc,常會忘了kernel
 # ln -s /etc/FREEBSD ./
d.編輯 kernel 新的文字敘述檔
  在最後面加入這幾行...以便打開Firewall and Quota 的功能

  options IPFIREWALL
  options IPDIVERT
  options QUOTA
e.做 config:
 # cd /usr/src/sys/i386/conf
 # config FREEBSD // FREEBSD 為我們先前編好的文字敘述檔名
 # cd /usr/src/sys/compile/FREEBSD
 # make depend
 # make
 # make install

g .完成後先行重新開機...若成功開機...恭喜...
 # cd /usr/src/sys/compile/FREEBSD
 # make clean
 (1) lsmod //看現在所用的kernel
 (2) unload //把不能開機的(正確應該說是現行的)kernel unload
 (3) ls //看看現在有哪些檔案
 (4) load kernel.GENERIC //load原先FreeBSD預設的GENERIC kernel
 (5) boot //繼續開機

* 架設 Mail+Pop3+Quota :

Sendmail -->收信、發信 25 port (sendmail基本來說不用額外安裝)
pop3 -->取信 110 port

POP3 Server:
qpop3 -->freebsd最常用
# cd /usr/ports/mail/qpopper
# make install clean;
# vi /etc/inetd.conf
pop3 stream tcp nowait root /usr/local/libexec/qpopper qpopper -s
然後把 inetd 重啟
# kill -HUP ` cat /var/run/inetd.pid `
# vi /usr/local/etc/qpopper/popusers
設定Quota :
# cd /etc
# vi fstab
/dev/da0s2e /var/mail ufs rw,userquota 2 2
注意: 在這邊是 userquota ... 而如果是 Linux 的話...是 usrquota ...少一個字差很多囉...

修改 rc.conf 讓 Quota 一開機就啟動:
# vi rc.conf
然後把 inetd 重啟
# kill -HUP ` cat /var/run/inetd.pid `

* 架設 NAT 及 Firewall Server :

有三個防護的要素:port, host, protocol
1.filter packets
IPFW這兩種都可作,可直接用在FreeBSD機器或當gateway router,保護LAN中的多部機器。
或是不要重新編譯核心,而是利用/etc/rc.network script自動載入kernel module,在/etc/rc.conf加入幾個項目
# vi /etc/rc.conf
若沒有指定firewall_type,會使用預設編號65535的rule:deny ip from any to any
# /etc/netstart
Flushed all rules.
00050 divert 8668 ip from any to any via de0
00100 allow ip from any to any via lo0
00200 deny ip from any to
00300 deny ip from to any
65000 allow ip from any to any
Firewall rules loaded, starting divert daemons:
現在可使用ipfw來設定rule,允許哪種traffic或檢視accounting information
ipfw用來自packet filter或account system中add或delete規則(rule)
action: deny, allow
protocol: tcp, udp, all
address: from, to
#/sbin/ipfw add deny tcp from badguy.com to any
#/sbin/ipfw add deny all from bad.ip.com/16 to www.anyplace.com 80
#/sbin/ipfw add allow all from goodone.bad.ip.com to www.anyplace.com 80
# ipfw -a list
00050 62 4840 divert 8668 ip from any to any via de0
00100 0 0 allow ip from any to any via lo0
00200 0 0 deny ip from any to
00300 0 0 deny ip from to any
65000 60 4484 allow ip from any to any
65535 2 356 allow ip from any to any
/sbin/ipfw add deny tcp from badguy.com to any
/sbin/ipfw add deny all from bad.ip.com/16 to www.anyplace.com 80
/sbin/ipfw add allow all from goodone.bad.ip.com to www.anyplace.com 80
/sbin/ipfw add 65000 allow all from any to any
下回重新開機或執行/etc/netstart會以100, 200, 300的編號順序載入/etc/firewall.conf中的規則。

* 網路應用(一) Webmin :

# cd /usr/ports/sysutils/webmin
# make install clean;
# /usr/local/etc/webmin/start
如果您裝的時後有選擇SSL的話...才需要在這邊打 https

* 網路應用(二) Mrtg :

# cd /usr/ports/net/net-snmp/
# make install clean ;
# /usr/local/sbin/snmpd
net-snmp 的版本是 5.x 版的請注意
# vi /usr/local/share/snmp/snmpd.conf
rocommunity mrtg
(意思為只唯讀 snmp 資訊的 username)
然後重新啟動你的 snmpd
安裝MRTG :
# cd /usr/ports/net/mrtg/
# make install clean ;
# cd /usr/local/etc/mrtg/
# cfgmaker mrtg@freebsd.commerce.com.tw > mrtg.cfg
* 在產生index.htm檔之前..別忘了在您的設定檔中加上一行 Workdir:完整路徑
Workdir: /usr/local/www/data/mrtg
# 如果要使用中文的 MRTG 則加入下面這一行
Language: big5
# 預設的 MRTG 所產生的圖時間是由右到左
# 我喜歡由左到右,故加入下面這一行
Options[_]: growright
然後使用指令 indexmaker 來建立 MRTG 的首頁:
# indexmaker mrtg.cfg > /usr/local/www/data/mrtg/index.htm
輸出的檔案 index.htm 你也可以使用其他的網頁編輯軟體再
去修改美化它。接下來要將MRTG的一些圖片檔複製到 mrtg 的目錄裡:
# cd /usr/ports/distfiles
# tar zxvf mrtg-2.9.25.tar.gz
# cd mrtg-2.9.25
# cp -rf images/* /usr/local/www/data/mrtg/
# /usr/local/bin/mrtg /usr/local/etc/mrtg/mrtg.cfg

用crontab定期執行 (每5分鐘執行一次)
# crontab -e
*/5 * * * * /usr/local/bin/mrtg /usr/local/etc/mrtg/mrtg.cfg
打開 Browser 測試 :

* 網路應用(三) Openwebmail :  

# cd /usr/ports/mail/openwebmail
# make all install clean;
別懷疑...你已經裝好openwebmail 了...這個是個人認為最好裝的一個啦...

* 網路應用(四) phpMyAdmin :  
# cd /usr/ports/databases/phpmyadmin
# make install clean;
# mv /usr/local/www/data.default/phpMyAdmin /usr/local/www/data/phpmyadmin
# cd /usr/local/www/data/phpmyadmin
# cp config.inc.php.sample config.inc.php
# vi config.inc.php
$cfg['PmaAbsoluteUri'] = 'http://www.yourip.com.tw/phpmyadmin';
$cfg['Servers'][$i]['auth_type'] = 'http'; // Authentication method (config, http or cookie based)?
$cfg['Servers'][$i]['user'] = 'root'; // MySQL user
$cfg['Servers'][$i]['password'] = 'Password'; // MySQL password (only needed

* SWAT(Samba Web Configuration Tool) :

# vi /etc/inetd.conf

#swat stream tcp nowait/400 root /usr/local/sbin/swat swat
將最後一行的 # 拿掉變成
swat stream tcp nowait/400 root /usr/local/sbin/swat swat

* 掃描工具 Nmap :

# cd /usr/ports/security/nmap
# make all install clean;
操作使用 :
# nmap -v -sS -O www.doamin.com.tw
詳細部份可以只下 nmap 會有簡單說明...

Wednesday, March 25, 2009

[support] MyISAM vs InnoDB

[support] MyISAM vs InnoDB
Kieran Lal kieran at acquia.com
Sat Mar 21 20:25:29 UTC 2009

Previous message: [support] MyISAM vs InnoDB
Next message: [support] MyISAM vs InnoDB
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]


On Sat, Mar 21, 2009 at 1:16 PM, Daniel Carrera
> Kieran Lal wrote:
>> Tell us more about your site. Number of nodes, users, traffic. What
>> kind of hosting environment, etc?
>> InnoDB is safer, but consumes more resources.
> Hmm... let's see... 7,152 nodes, 4,300 users, and if I read the monthly log
> correctly, it seems like it averages 15,300 hits/day with a peak of 18,000
> hits/day on wednesdays. But I think that might include all the files that go
> into making a web page (CSS, logo, etc).
> We have a shared hosting environment, of the type that doesn't over-sell
> disk space, so it is somewhat intermediate between a typical shared hosting
> and a dedicated host.
> The servers run RHEL, PHP 5.2.8 and MySQL 5.1.30.
> Uhm... I can't think of anything else I can say about the site. Does any of
> this help answer my question?

MySQL ISAM engine is lightweight, and not transactional, but has been
know to corrupt, although I think it's much more stable in MySQL 5.1.
For high performance, and transaction integrity many people move their
database engine to InnoDB.

InnoDB uses ~5x the disk space and ~3x more memory. It can be faster,
and more reliable. But the down side is that if big tables like node,
watchdog are InnoDB you can run into problems. Based on your site
size, I don't forsee moving your entire site to InnoDB to be a

Here's a Drupal performance tuning checklist:

If you see a slowdown, let me know and I'll help you out.


> Daniel.
> --
> [ Drupal support list | http://lists.drupal.org/ ]

I use InnoDB myself. I suggest the innodb_file_per_table configuration
option to help control the size issue. If you create a table and then
remove it this option will return all the disk space, otherwise you
continue to use it.

Earnie http://r-feed.com
Make a Drupal difference and review core patches.

It really depends on what you need to do. If you don't know it I'd
go for MyISAM since most of the features you may be looking for in
InnoDB are not really fully exploited by stock Drupal.

The reasons that may make you chose InnoDB may be the same to
consider to add to the list PostgreSQL, but it really depends on
what is your specific need.

Consider that anyway PostgreSQL support is (was) not as good as
MySQL, anyway I never had serious issues.

The main annoyance was waiting some patch got included into core and
having to re-patch every time a new point release comes out.

But in my experience the problems you may run into can be patched in
5 min.

Summing it up:

Drupal doesn't have support for transaction or referential integrity
but you may need it if you're developing your own modules.
If you've several writes or high concurrency and data integrity is
important PostgreSQL may be an interesting option.

If you've a lot of read, and you don't mind having to deal with
some inconsistency , MyISAM and replication may be fine.

I think InnoDB is "in between" without shining for any aspect.
If I were looking for transactions and data integrity I'd take the
InnoDB route just if I already invested a lot in MySQL.

Ivan Sergio Borgonovo

I just wrote another post that explains my hosting environment. I am
interested in speed and reliability (isn't everybody?). My understanding
is that:

1) InnoDB is more reliable.
2) InnoDB reads faster, if the primary keys and indexes are set right.
3) InnoDB writes slower.
4) InnoDB requires more disk space and more RAM.

Am I right so far? I'm not very familiar with this topic.

I'm not very concerned about disk space. I'm happy to make the DB 20%
bigger if it'll improve read speed and reliability. But I don't fully
understand the implications of InnoDB vs MyISAM, so I thought I'd ask here.

> The reasons that may make you chose InnoDB may be the same to
> consider to add to the list PostgreSQL, but it really depends on
> what is your specific need.

I thought that the main benefit of PostgreSQL was advanced features
(procedures, triggers, etc). I don't use any of those. I'm just looking
for speed an reliability.

PostgreSQL is a way better than MySQL, about all topics.
The only thing on which MySQL could be better, is maybe it's faster on
read operations on small databases.
But, in fact, PostgreSQL can handle correctly really BIG databases, with
a really big amount of data, and is easier to cluster.
PostgreSQL is more stable, secure, and a more efficient and flawless
with stocked procedures and triggers.

If you have to choose between MyISAM and InnoDB, if I were you, I'd
choose InnoDB, it's a lot more stable. MyISAM may be faster and eat less
disk space, but you may have really bad surprises with your data

In the company I work for, we used to make a MySQL intensive use, the
first monthes, we abandon MyISAM for a lot of obvious reasons. And right
now, we are abandoning MySQL in flavor of PostgreSQL.

We still use MySQL for Drupal, because a lot of module developpers still
can't write standard SQL, but, if all modules were PostgreSQL aware, we
would not use MySQL at all.

This a my opinion, from my experience, I may be wrong.

Do the right choice, don't do IT :)


It's true, PostgreSQL really has a lot of cool features. But it's also
true that it provides a fully ACID (Atomicity, Consistency, Isolation,
Durability) compliant database, which MySQL does not until the future 6
In PG database, every request, even a single simple one, is executed in
a transactionnal context. This is also true with triggers and

I quote "PostgreSQL is fully ACID-compliant, while MySQL's InnoDB
storage engine provides engine-level ACID-compliance" (see

Even with clustering, PostgreSQL seems to be a lot more powerfull, since
you can use cross databases constraints between tables from more than
one PG instance. You can also do table partitioning, and a lot of other
cool features to help you when you start having *A LOT* of data :)

MyISAM, InnoDB and PostgreSQL perform differently on different
Ease of development and safety of data may have an indirect impact
on speed as well.

For some tasks MyISAM is reliable enough and "failure" won't impact
the "average" speed. Once you add replication it may become your
best solution.

I think that outside that scenario the only 2 good reason to chose
InnoDB over PostgreSQL are:
- you invested a lot in MySQL (your staff is made of MySQL black
- you want to lower as much as possible the cost of maintaining
drupal sites and still data integrity and frequent writes aren't
your first priority but you're starting to feel the pain of
MyISAM. In my view most of the time this is going to be a
"diplomatic" choice... still not a "we seriously would like a bit
more data integrity/concurrency but we can't afford PostgreSQL"
choice. Once you're in the territory of "a bit more data integrity
and concurrency" you've already passed the threshold that will
make maintaining MySQL cheaper.

So most of the times the real reason to keep using InnoDB vs.
PostgreSQL is your knowledge of the tool.

In most if not all the situations where you may chose InnoDB over
MyISAM just on technical merits, PostgreSQL would be a better
candidate... since there are other constraint that may influence
your choice you may still prefer InnoDB.

And... as Michael Prasuhn wrote most of the sites don't have to deal
with the problems InnoDB try to solve and when they run into them
they have built up so much (too much?) MySQL knowledge and invested
so much in MySQL tuning/coding that their best move is to switch to

Ivan Sergio Borgonovo

A lot of confusion here, from others, not just Daniel. Overall the
biggest benefit is that InnoDB supports row-level locking versus table-
locking on writes. For high traffic sites this can make some obvious
benefits for tables like access logs, sessions, users, comments,
node_comment_statistics and the like.

The downside is that for reading large amounts of simple data, InnoDB
is slower than MyISAM. In fact MyISAM is probably one of the fastest
engines out there in terms of reading data.

In short, unless you know you have large waits doing common tasks such
as insert comments when the load on the site is high, or you have a
way to examine how many connections are waiting on table locks before
completion, you are probably best off sticking with MyISAM.

Also, while InnoDB is widely available these days, you may still run
into hosts that don't support it, but do support MyISAM.

I don't think speed is really the problem here. There are a lot of wide
architectures that uses PostgreSQL or other DBMS's under very high load.
There are now a lot of solution to support high loads, and most of them
are based on redondancy and large amount of memory. Use a fast DBMS, ok,
but use a REAL DBMS, they are, in fact, fast enough.

The fact MyISAM reads fast, is the concequencies of its lack of security
and features.
Don't kill the kitten, don't use MyISAM.

Indeed, keeping such engine alive is an heresy, because it's not ACID
compliant, even if Drupal does not use transactions or referencial
integrity, this is a very bad habit to continue to use it.

Your conclusion makes sens, some hosters continues to use outdated
technos such as MyISAM. But in case you are starting a new architecture
of your own somewhere, I really disencourage you to use MyISAM.
> Could you confirm that row-level locking means that you can do
> multiple INSERTs at the same time?
> Suppose that you are going to do 50 INSERTs in one transaction (my
> non-Drupal site does this at one place). Can two users do the 50-
> INSERT operation at the same time? (the application is a markbook/
> gradebook - the inserts are the marks/grades for 50 students).

Well there are some gotcha conditions, if you have a WHERE clause in
your update, it must be using an index, otherwise it has to do a table
scan, and locks the whole table. Also, any inserts using an auto-
increment column will lock the entire table to prevent duplicate values.

> I thought that InnoDB was supposed to be faster for reading. At
> least, for reading rows that are related by index (e.g. users 1-20
> assuming that "user id" is an index).

Please see http://2bits.com/articles/mysql-innodb-performance-gains-as-well-as-some-pitfalls.html
for some examples.


> Michael Prasuhn wrote:
>> A lot of confusion here, from others, not just Daniel. Overall the
>> biggest benefit is that InnoDB supports row-level locking versus
>> table-locking on writes.
> Could you confirm that row-level locking means that you can do
> multiple INSERTs at the same time?
> Suppose that you are going to do 50 INSERTs in one transaction (my
> non-Drupal site does this at one place). Can two users do the
> 50-INSERT operation at the same time? (the application is a
> markbook/gradebook - the inserts are the marks/grades for 50
> students).

If the operation is transactionalized and the users are updating some
of the same rows the one who updates last looses because the engine is
smart enough to know that the second update cannot be allowed to happen
because the signature of the row has changed; the user can then be
warned that the data changed prior to his update. Or, in some cases,
the rows can be locked up front so the second user waits on the first
user to release the data rows before he can even view the data. In the
non-transactinalized case the second update wins and the original
update is lost without warning; we see this in the issue queue quite
often with people changing the status column from the changed value to
previous value incidentally.


> It really depends on what you need to do. If you don't know it
> > I'd go for MyISAM since most of the features you may be looking
> > for in InnoDB are not really fully exploited by stock Drupal.

> Well, not yet anyway. http://drupal.org/node/301362

Supporting MyISAM, sqlite and advanced (I'd say standard) features
of serious RDBMS doesn't look a viable way to develop drupal (unless
the DB abstraction layer is outsourced, but this would(?) be more
suited for another flame ;) )

I consider normal to add "ON DELETE CASCADE" actions, but to
replicate it transparently in PHP it is a hell of a work.
And that's just one example.

My point is:
- if you're not using "advanced" features and you're not constrained
by concurrent writes MyISAM is good enough. I'd say MyISAM may be
even better suited to Drupal than InnoDB. None of the two engines
is famous for data integrity after all.
- if you're using advanced features, you're constrained by
concurrent writes, you can't afford data loss and you didn't
invest too much in MySQL there are better engines to look at.

Choosing InnoDB would be just a matter of how much you invested
in MySQL.

I don't think that once you're faced with these problems your hosting
offer is a real concern.
Data integrity is understood as respecting the relationships between tables.
So, if there are several tables in a one to many relationship with the node
table, say, for a CCK based content type, if the node is deleted, then the
child records would also be deleted.

and you would not be allowed to delete a parent without also deleting

yep... but doing this in PHP is a pain, doing it in PHP and in SQL
is a double pain.
And unless support for MyISAM and sqlite is going to be dropped, and
I don't think right now is a good choice, using more "advanced"
DB features in core would be a double pain.

Another thing is helping people to exploit more advanced features in
their modules. Modules may have more exotic requirements than core.

I don't know about sqlite but MyISAM would continue to work even if we
code for the transactional update. It would just lock tables instead
of rows and the cascading would not occur. If warned it would be up to
the user to make a determination to continue with MyISAM or move to a
new provider.

Pattern Modifiers regular expression UTF-8

Pattern Modifiers
The current possible PCRE modifiers are listed below. The names in parentheses refer to internal PCRE names for these modifiers. Spaces and newlines are ignored in modifiers, other characters cause error.

If this modifier is set, letters in the pattern match both upper and lower case letters.
By default, PCRE treats the subject string as consisting of a single "line" of characters (even if it actually contains several newlines). The "start of line" metacharacter (^) matches only at the start of the string, while the "end of line" metacharacter ($) matches only at the end of the string, or before a terminating newline (unless D modifier is set). This is the same as Perl. When this modifier is set, the "start of line" and "end of line" constructs match immediately following or immediately before any newline in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m modifier. If there are no "\n" characters in a subject string, or no occurrences of ^ or $ in a pattern, setting this modifier has no effect.
If this modifier is set, a dot metacharacter in the pattern matches all characters, including newlines. Without it, newlines are excluded. This modifier is equivalent to Perl's /s modifier. A negative class such as [^a] always matches a newline character, independent of the setting of this modifier.
If this modifier is set, whitespace data characters in the pattern are totally ignored except when escaped or inside a character class, and characters between an unescaped # outside a character class and the next newline character, inclusive, are also ignored. This is equivalent to Perl's /x modifier, and makes it possible to include comments inside complicated patterns. Note, however, that this applies only to data characters. Whitespace characters may never appear within special character sequences in a pattern, for example within the sequence (?( which introduces a conditional subpattern.
If this modifier is set, preg_replace() does normal substitution of backreferences in the replacement string, evaluates it as PHP code, and uses the result for replacing the search string. Single quotes, double quotes, backslashes and NULL chars will be escaped by backslashes in substituted backreferences.
Only preg_replace() uses this modifier; it is ignored by other PCRE functions.

If this modifier is set, the pattern is forced to be "anchored", that is, it is constrained to match only at the start of the string which is being searched (the "subject string"). This effect can also be achieved by appropriate constructs in the pattern itself, which is the only way to do it in Perl.
If this modifier is set, a dollar metacharacter in the pattern matches only at the end of the subject string. Without this modifier, a dollar also matches immediately before the final character if it is a newline (but not before any other newlines). This modifier is ignored if m modifier is set. There is no equivalent to this modifier in Perl.
When a pattern is going to be used several times, it is worth spending more time analyzing it in order to speed up the time taken for matching. If this modifier is set, then this extra analysis is performed. At present, studying a pattern is useful only for non-anchored patterns that do not have a single fixed starting character.
This modifier inverts the "greediness" of the quantifiers so that they are not greedy by default, but become greedy if followed by "?". It is not compatible with Perl. It can also be set by a (?U) modifier setting within the pattern or by a question mark behind a quantifier (e.g. .*?).
This modifier turns on additional functionality of PCRE that is incompatible with Perl. Any backslash in a pattern that is followed by a letter that has no special meaning causes an error, thus reserving these combinations for future expansion. By default, as in Perl, a backslash followed by a letter with no special meaning is treated as a literal. There are at present no other features controlled by this modifier.
The (?J) internal option setting changes the local PCRE_DUPNAMES option. Allow duplicate names for subpatterns.
This modifier turns on additional functionality of PCRE that is incompatible with Perl. Pattern strings are treated as UTF-8. This modifier is available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32. UTF-8 validity of the pattern is checked since PHP 4.3.5.

Differences From Perl PCRE Patterns
Last updated: Fri, 20 Mar 2009

add a note User Contributed Notes
Possible modifiers in regex patterns
ebarnard at marathonmultimedia dot com
06-Feb-2007 10:35
When adding comments with the /x modifier, don't use the pattern delimiter in the comments. It may not be ignored in the comments area. Example:

$target = 'some text';
e # Comments here
/x',$target)) {
print "Target 1 hit.\n";
e # /Comments here with slash
/x',$target)) {
print "Target 1 hit.\n";

prints "Target 1 hit." but then generates a PHP warning message for the second preg_match():

Warning: preg_match() [function.preg-match]: Unknown modifier 'C' in /ebarnard/x-modifier.php on line 11
varrah NO_GARBAGE_OR_SPAM AT mail DOT ru
03-Nov-2005 12:12
Spent a few days, trying to understand how to create a pattern for Unicode chars, using the hex codes. Finally made it, after reading several manuals, that weren't giving any practical PHP-valid examples. So here's one of them:

For example we would like to search for Japanese-standard circled numbers 1-9 (Unicode codes are 0x2460-0x2468) in order to make it through the hex-codes the following call should be used:
preg_match('/[\x{2460}-\x{2468}]/u', $str);

Here $str is a haystack string
\x{hex} - is an UTF-8 hex char-code
and /u is used for identifying the class as a class of Unicode chars.

Hope, it'll be useful.
hfuecks at nospam dot org
15-Jul-2005 02:14
Regarding the validity of a UTF-8 string when using the /u pattern modifier, some things to be aware of;

1. If the pattern itself contains an invalid UTF-8 character, you get an error (as mentioned in the docs above - "UTF-8 validity of the pattern is checked since PHP 4.3.5"

2. When the subject string contains invalid UTF-8 sequences / codepoints, it basically result in a "quiet death" for the preg_* functions, where nothing is matched but without indication that the string is invalid UTF-8

3. PCRE regards five and six octet UTF-8 character sequences as valid (both in patterns and the subject string) but these are not supported in Unicode ( see section 5.9 "Character Encoding" of the "Secure Programming for Linux and Unix HOWTO" - can be found at http://www.tldp.org/ and other places )

4. For an example algorithm in PHP which tests the validity of a UTF-8 string (and discards five / six octet sequences) head to: http://hsivonen.iki.fi/php-utf8/

The following script should give you an idea of what works and what doesn't;

$examples = array(
'Valid ASCII' => "a",
'Valid 2 Octet Sequence' => "\xc3\xb1",
'Invalid 2 Octet Sequence' => "\xc3\x28",
'Invalid Sequence Identifier' => "\xa0\xa1",
'Valid 3 Octet Sequence' => "\xe2\x82\xa1",
'Invalid 3 Octet Sequence (in 2nd Octet)' => "\xe2\x28\xa1",
'Invalid 3 Octet Sequence (in 3rd Octet)' => "\xe2\x82\x28",

'Valid 4 Octet Sequence' => "\xf0\x90\x8c\xbc",
'Invalid 4 Octet Sequence (in 2nd Octet)' => "\xf0\x28\x8c\xbc",
'Invalid 4 Octet Sequence (in 3rd Octet)' => "\xf0\x90\x28\xbc",
'Invalid 4 Octet Sequence (in 4th Octet)' => "\xf0\x28\x8c\x28",
'Valid 5 Octet Sequence (but not Unicode!)' => "\xf8\xa1\xa1\xa1\xa1",
'Valid 6 Octet Sequence (but not Unicode!)' => "\xfc\xa1\xa1\xa1\xa1\xa1",

echo "++Invalid UTF-8 in pattern\n";
foreach ( $examples as $name => $str ) {
echo "$name\n";

echo "++ preg_match() examples\n";
foreach ( $examples as $name => $str ) {

preg_match("/\xf8\xa1\xa1\xa1\xa1/u", $str, $ar);
echo "$name: ";

if ( count($ar) == 0 ) {
echo "Matched nothing!\n";
} else {
echo "Matched {$ar[0]}\n";


echo "++ preg_match_all() examples\n";
foreach ( $examples as $name => $str ) {
preg_match_all('/./u', $str, $ar);
echo "$name: ";

$num_utf8_chars = count($ar[0]);
if ( $num_utf8_chars == 0 ) {
echo "Matched nothing!\n";
} else {
echo "Matched $num_utf8_chars character\n";

csaba at alum dot mit dot edu
09-Apr-2005 12:40
Extracting lines of text:

You might want to grab a line of text within a multiline piece of text. For example, suppose you want to replace the first and last lines within the <body> portion of a web $page with your own $lineFirst and $lineLast. Here's one possible way:

$lineFirst = "This is a new first line<br>\r\n";
$lineLast  = "This is a new last line<br>\r\n";
$page = <<<EOD
<title>This is a test page</title>
This is the first line<br>
Hi Fred<br>
Hi Bill<br>
This is the last line<br>
$re = "/<body>.*^(.+)(^.*?^)(.+)(^<\\/body>.*?)/smU";
if (preg_match($re, $page, $aMatch, PREG_OFFSET_CAPTURE))
$newPage = substr($text, 0, $aMatch[1][1]) .
$lineFirst . $aMatch[2][0] .
$lineLast . $aMatch[4][0];
print $newPage;

The two (.+) are supposed to match the first and last lines within the <body> tag. The /s option (dot all) is needed so the .* can also match newlines. The /m option (multiline) is needed so that the ^ can match newlines. The /U option (ungreedy) is needed so that the .* and .+ will only gobble up the minimum number of characters necessary to get to the character following the * or +. The exception to this, however, is that the .*? temporarily overrides the /U setting on .* turning it from non greedy to greedy. In the middle, this ensures that all the lines except the first and last (within the <body> tag) are put into $aMatch[2]. At the end, it ensures that all the remaining characters in the string are gobbled up, which could also have been achieved by .*)\\z/ instead of .*?)/

Csaba Gabor from Vienna

Drupal 4.7 Drupal 5 Drupal 6 Drupal 7 includes/bootstrap.inc, line 766

Versions 4.7 – 7 drupal_validate_utf8($text)
Checks whether a string is valid UTF-8.

All functions designed to filter input should use drupal_validate_utf8 to ensure they operate on valid UTF-8 strings to prevent bypass of the filter.

When text containing an invalid UTF-8 lead byte (0xC0 - 0xFF) is presented as UTF-8 to Internet Explorer 6, the program may misinterpret subsequent bytes. When these subsequent bytes are HTML control characters such as quotes or angle brackets, parts of the text that were deemed safe by filters end up in locations that are potentially unsafe; An onerror attribute that is outside of a tag, and thus deemed safe by a filter, can be interpreted by the browser as if it were inside the tag.

This function exploits preg_match behaviour (since PHP 4.3.5) when used with the u modifier, as a fast way to find invalid UTF-8. When the matched string contains an invalid byte sequence, it will fail silently.

preg_match may not fail on 4 and 5 octet sequences, even though they are not supported by the specification.

The specific preg_match behaviour is present since PHP 4.3.5.

$text The text to check.

Return value
TRUE if the text is valid UTF-8, FALSE if not.

2 functions call drupal_validate_utf8()
2 functions call drupal_validate_utf8()
check_plain in includes/bootstrap.inc
Encode special characters in a plain-text string for display as HTML.
filter_xss in modules/filter/filter.module
Filters XSS. Based on kses by Ulf Harnhammar, see http://sourceforge.net/projects/kses
function drupal_validate_utf8($text) {
if (strlen($text) == 0) {
return TRUE;
return (preg_match('/^./us', $text) == 1);

Tuesday, March 24, 2009

Building a multi-language site with Drupal 6

Building a multi-language site with Drupal 6

Submitted by toma on Sun, 11/16/2008 - 15:28.
The following steps are for those who want to have a simple site available in deferent languages. The goal is to have content translated to two or more languages and the visitor to be able to choose any of them. Also, the menus must follow the selection. I have tested the result with content types page and story. I don't know what happens with forum, for example. I hope this helps you.

In the parentheses I give the relative path in the url. So, if your site is http://example.com/drupal and in parentheses I give admin/build/modules, then the url becomes: http://example.com/drupal/admin/build/modules

Install Internationalization module
Go to the modules (admin/build/modules) and in Core - optional section enable
Content translation
In the Multilanguage - i18n section enable all available. If you haven't enabled Poll and Profile modules, Drupal asks you if you want them enabled. If you don't want them, in the Multilanguage - i18n don't enable Multilanguage Poll and Multilanguage Profile.
You now need the translation files for all the available languages of your site (if you haven't them already). Go to the translations page and download. Then extract them to Drupal's folder (see at 2 minutes 30 seconds into this videocast for the correct way to extract translations; you can ignore the rest of the video as it deals with installing Drupal in a language other than English, while this page deals with adding a language after Drupal has already been installed).

You have to add this language:

Go to the Languages page (admin/settings/language)
Add all the languages you downloaded and extracted (admin/settings/language/add)
Choose Configure
In the Language negotiation choose Path prefix only and save settings
Make sure English is the default language
Go to the blocks (admin/build/block)
In the Disabled area choose a Region for the Language switcher
Choose Save blocks
Ok, now you are at a good point. Choosing a language from the Language switcher, the Built-in interface changes to the corresponding language! If it doesn't make sure that it is translated. For that, navigate to admin/build/translate and check the ratio. It must be close to 100%.

The next steps are to make multilingual content.

Enable Multilingual support for all content types you want (admin/content/types)
Choose edit for the content type you want (e.g page)
In the Workflow settings choose Enabled, with translation and save
Now create content for the content type you have enabled multilingual support (e.g a page) (node/add/page)
In the Language field choose English
Save the page
Choose the Translate link
Choose add translation for the language you want
Write the page. The value in the Language field should show the selected language and be disabled/greyed out.
Now you should be able to switch between translations when viewing the page by using the Language switcher block.

You might want to use flags instead, in which case you'll need the Language Icons module.

For your site to be fully translated you need to have the menus translated. You have two options!

Build a menu for every available language
Build one menu with links that point to every available language. What I mean is that if node/1 is your home page in English and node/2 in Greek, in your menu you have to make a link to node/1 named "Home Page" and one to node/2 named "Αρχική Σελίδα" (this is home page in Greek). You have to do this for every multilingual page.
Try both options and choose what is best for you.

1st option (multiple menus)

Add a new menu (admin/build/menu/add)
In the Menu name give a name, e.g. en-menu
Give title, description and Save
Add an item (admin/build/menu-customize/menu-en-menu/add)
Give the path for the English page (node/1)
Give the English name for the link
In the Language combo box you don't have to choose a language!
Add a new menu for the second language (admin/build/menu/add)
In the Menu name give a name, e.g. el-menu
Add an item (admin/build/menu-customize/menu-el-menu/add)
Give the path (node/2), name and save
Use the same procedure to build menus for all the available languages you have
Ok, you now have your menus. Let's display them.

Go to the blocks (admin/build/block)
Go the the Disabled area and choose a Region for your menus
Choose Save blocks
For your English menu choose configure under Operations column
In the Multilingual settings choose English as language and save
Do the same for the rest menus and choose the appropriate language
2nd option (one menu)

Add a new menu (admin/build/menu/add)
In the Menu name give a name, e.g. multi-menu
Give title, description and Save
Add an item (admin/build/menu-customize/menu-multi-menu/add)
Give the path for the English page (node/1)
Give the English name for the link
In the Language combo box choose English
Add another item (admin/build/menu-customize/menu-el-menu/add)
Give the path (node/2) and name
In the Language combo box choose your language, e.g. Greek
Do the same if node/1 is translated to more languages
Use the same procedure to build menus links for all the available pages you have multilingual
Now, display your menu

Go to the blocks (admin/build/block)
Go the the Disabled area and choose a Region for your menu
Choose Save blocks
Done! Now, when you choose a language on the language switcher, you should see the content translated and the correct menu.

View the tutorial
Building a multi-language site with Drupal 6
Source Site Information

Monday, March 23, 2009



FreeBSD Setting up Firewall using IPFW

FreeBSD Setting up Firewall using IPFW
by Vivek Gite

Q. I'm new to FreeBSD and am trying to configure the firewall using IPFW, but I'm having a hard time understanding it as compare to Linux. Can you provide a small example on how to go about setting up the rules for a typical FreeBSD based Apache Web server?

A. Ipfirewall (ipfw) is a FreeBSD IP packet filter and traffic accounting facility.

IPFW is included in the basic FreeBSD install as a separate run time loadable module. The system will dynamically load the kernel module when the rc.conf statement firewall_enable="YES" is used.

FreeBSD compile kernel for IPFW
This step is optional. You do not need to compile IPFW into the FreeBSD kernel unless you want NAT function enabled. However some old version may not have IPFW compiled. Here is a quick guide to compile kernel with IPFW.

Make sure IPFW support not compiled into the kernel:
#ipfw list

If you get an error that read as follows, you must now compile the source code for the kernel.
ipfw: getsockopt(IP_FW_GET): Protocol not available
Another option is open default kernel config file /usr/src/sys/i386/conf and look for IPFIREWALL option:
# grep IPFIREWALL /usr/src/sys/i386/conf

Building and Installing a Custom Kernel with IPFW
Copy default kernel file:
# cd /usr/src/sys/i386/conf

Add IPFW support:
Append following directives:
options IPFIREWALL # required for IPFW
options IPFIREWALL_VERBOSE # optional; logging
options IPFIREWALL_VERBOSE_LIMIT=10 # optional; don't get too many log entries
options IPDIVERT # needed for natd

Save and close the file. Building a Kernel, type following commnds:
# cd /usr/src
# make buildkernel KERNCONF=IPFWKERNEL

Install the new kernel:
# make installkernel KERNCONF=IPFWKERNEL

Now reboot the system:
# reboot

Step # 1: Enabling IPFW
Open /etc/rc.conf file
# vi /etc/rc.conf

Append following settings:
Save and close the file..

Step # 2 Write a Firewall Rule Script
You need to place a firewall rules in a script called /usr/local/etc/ipfw.rule:
# vi /usr/local/etc/ipfw.rules

Append following code:

IPF="ipfw -q add"
ipfw -q -f flush

$IPF 10 allow all from any to any via lo0
$IPF 20 deny all from any to
$IPF 30 deny all from to any
$IPF 40 deny tcp from any to any frag

# statefull
$IPF 50 check-state
$IPF 60 allow tcp from any to any established
$IPF 70 allow all from any to any out keep-state
$IPF 80 allow icmp from any to any

# open port ftp (20,21), ssh (22), mail (25)
# http (80), dns (53) etc
$IPF 110 allow tcp from any to any 21 in
$IPF 120 allow tcp from any to any 21 out
$IPF 130 allow tcp from any to any 22 in
$IPF 140 allow tcp from any to any 22 out
$IPF 150 allow tcp from any to any 25 in
$IPF 160 allow tcp from any to any 25 out
$IPF 170 allow udp from any to any 53 in
$IPF 175 allow tcp from any to any 53 in
$IPF 180 allow udp from any to any 53 out
$IPF 185 allow tcp from any to any 53 out
$IPF 200 allow tcp from any to any 80 in
$IPF 210 allow tcp from any to any 80 out

# deny and log everything
$IPF 500 deny log all from any to anySave and close the file.

Step # 3: Start a firewall
You can reboot the box or you could reload these rules by entering on the command line.
# sh /usr/local/etc/ipfw.rules

Task: List all the rules in sequence
Type the following command:
# ipfw list

Further readings:
Refer ipfw man page
Read IPFW chapter from FreeBSD handbook
Read the FreeBSD kernel configuration file format chapter from FreeBSD handbook
Updated for accuracy.

# Set this to your ip address.

# Allow anything outbound from this address.
${fwcmd} add allow all from ${ip} to any out

# Deny anything outbound from other addresses.
${fwcmd} add deny log all from any to any out

# Allow TCP through if setup succeeded.
${fwcmd} add allow tcp from any to any established

# Allow IP fragments to pass through.
${fwcmd} add allow all from any to any frag

# Allow all IPv6 packets through - they are handled by the separate
# ipv6 firewall rules in rc.firewall6.
${fwcmd} add allow ipv6 from any to any

# Allow inbound ftp, ssh, email, tcp-dns, http, https, imap, imaps,
# pop3, pop3s.
${fwcmd} add allow tcp from any to ${ip} 21 setup
${fwcmd} add allow tcp from any to ${ip} 22 setup
${fwcmd} add allow tcp from any to ${ip} 222 setup
${fwcmd} add allow tcp from any to ${ip} 25 setup
${fwcmd} add allow tcp from any to ${ip} 53 setup
${fwcmd} add allow tcp from any to ${ip} 80 setup
${fwcmd} add allow tcp from any to ${ip} 443 setup
${fwcmd} add allow tcp from any to ${ip} 143 setup
${fwcmd} add allow tcp from any to ${ip} 993 setup
${fwcmd} add allow tcp from any to ${ip} 110 setup
${fwcmd} add allow tcp from any to ${ip} 995 setup

# Deny inbound auth, netbios, ldap, and Microsoft's DB protocol
# without logging.
${fwcmd} add reset tcp from any to ${ip} 113 setup
${fwcmd} add reset tcp from any to ${ip} 139 setup
${fwcmd} add reset tcp from any to ${ip} 389 setup
${fwcmd} add reset tcp from any to ${ip} 445 setup

# Deny some chatty UDP broadcast protocols without logging.
${fwcmd} add deny udp from any 137 to any
${fwcmd} add deny udp from any to any 137
${fwcmd} add deny udp from any 138 to any
${fwcmd} add deny udp from any 513 to any
${fwcmd} add deny udp from any 525 to any

# Allow inbound DNS and NTP replies. This is somewhat of a hole,
# since we're looking at the incoming port number, which can be
# faked, but that's just the way DNS and NTP work.
${fwcmd} add allow udp from any 53 to ${ip}
${fwcmd} add allow udp from any 123 to ${ip}

# Allow inbound DNS queries.
${fwcmd} add allow udp from any to ${ip} 53

# Allow inbound NTP queries.
${fwcmd} add allow udp from any to ${ip} 123

# Allow traceroute to function, but not to get in.
${fwcmd} add unreach port udp from any to ${ip} 33435-33524

# Allow some inbound icmps - echo reply, dest unreach, source quench,
# echo, ttl exceeded.
${fwcmd} add allow icmp from any to any icmptypes 0,3,4,8,11

# Everything else is denied and logged.
${fwcmd} add deny log all from any to any

Sunday, March 22, 2009






Saturday, March 21, 2009



Friday, March 20, 2009






































真正的自信來自知識 ~ 它是由己身出發 . 散發於個人舉手投足的氣質之內
在感覺上來說 . 它比所謂的有恃無恐更為輕鬆與高層次

自信兩字 . 一般的認知都忽略囉"自"這個字
所謂靠山山倒 . 靠人人倒 . 靠自己最好
真自信是不靠它人眼光 . 很純粹的自我認知與感覺
但非自我封閉 . 而是全面開放的心理狀態

樂觀 . 積極 . 豁達 .... 由此而來

Thursday, March 19, 2009

truss -- trace system calls - problem with apache benchmark

problem with apache benchmark

Bartosz Giza wrote:


from couple of days i am trying to figure out what is wrong with apache
bench. I want to test my remote site with it but all the time i got this
error message.

% ab -c 10 -n 500 http://xxxxx/test.php
Test aborted after 10 failures

apr_socket_connect(): Operation already in progress (37)
Total of 8 requests completed

I would use truss to look at the syscalls ab is using. Make sure /proc
is mounted and use "truss ab" instead of just ab. Also checking the
httpd logs in /var/log might be useful.

I've used ab locally on a recent 6.2 and I don't get this failure, but
my ab and my kernel are likely different.


I searched google but i didn't find anything in english that i could use.
Could somebody help me with this.

I am running freebsd 6.2-PRE. I have tested this on amd64 and i386.
It seems that there is problem with -c 10 parametr. Without this param ab
works good (i hope). But without -c it is hard to benchmark my apache

Debugging technique: capture and email your ouput

Debugging technique: capture and email your ouput
Submitted by Eric on Wed, 08/13/2008 - 08:38
Tags:debug email Mail ob_end_clean ob_get_contents ob_start
Here's a quick debugging technique to capture your output and email it to yourself. This can be useful when you cannot send your debug output to the browser.

// start output buffer

// display the contents of your variable

// get the contents of the output buffer
$ob = ob_get_contents();

// stop output buffer

// mail contents of output buffer to yourself
mail('YOUREMAIL','Output Buffer Contents',$ob);

Howto: Performance Benchmarks a Webserver

Howto: Performance Benchmarks a Webserver
by nixcraft

You can benchmark Apache, IIS and other web server with apache benchmarking tool called ab. Recently I was asked to performance benchmarks for different web servers.

It is true that benchmarking a web server is not an easy task. From how to benchmark a web server:

First, benchmarking a web server is not an easy thing. To benchmark a web server the time it will take to give a page is not important: you don't care if a user can have his page in 0.1 ms or in 0.05 ms as nobody can have such delays on the Internet.

What is important is the average time it will take when you have a maximum number of users on your site simultaneously. Another important thing is how much more time it will take when there are 2 times more users: a server that take 2 times more for 2 times more users is better than another that take 4 times more for the same amount of users."

Here are few tips to carry out procedure along with an example:

Apache Benchmark Procedures
You need to use same hardware configuration and kernel (OS) for all tests
You need to use same network configuration. For example, use 100Mbps port for all tests
First record server load using top or uptime command
Take at least 3-5 readings and use the best result
After each test reboot the server and carry out test on next configuration (web server)
Again record server load using top or uptime command
Carry on test using static html/php files and dynamic pages
It also important to carry out test using the Non-KeepAlive and KeepAlive (the Keep-Alive extension to provide long-lived HTTP sessions, which allow multiple requests to be sent over the same TCP connection) features
Also don't forget to carry out test using fast-cgi and/or perl tests
Webserver Benchmark Examples:
Let us see how to benchmark a Apache 2.2 and lighttpd 1.4.xx web server.

Static Non-KeepAlive test for Apache web server
i) Note down server load using uptime command
$ uptime
ii) Create a static (small) html page as follows (snkpage.html) (assuming that server IP is in /var/www/html (or use your own webroot):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<title>Webserver test</title>
This is a webserver test page.
Login to Linux/bsd desktop computer and type following command:
$ ab -n 1000 -c 5

-n 1000: ab will send 1000 number of requests to server in order to perform for the benchmarking session
-c 5 : 5 is concurrency number i.e. ab will send 5 number of multiple requests to perform at a time to server
For example if you want to send 10 request, type following command:
$ ab -n 10 -c 2 http://www.somewhere.com/

This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/

Benchmarking www.cyberciti.biz (be patient).....done

Server Software:
Server Hostname: www.somewhere.com
Server Port: 80

Document Path: /
Document Length: 16289 bytes

Concurrency Level: 1
Time taken for tests: 16.885975 seconds
Complete requests: 10
Failed requests: 0
Write errors: 0
Total transferred: 166570 bytes
HTML transferred: 162890 bytes
Requests per second: 0.59 [#/sec] (mean)
Time per request: 1688.597 [ms] (mean)
Time per request: 1688.597 [ms] (mean, across all concurrent requests)
Transfer rate: 9.59 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 353 375 16.1 386 391
Processing: 1240 1312 52.1 1339 1369
Waiting: 449 472 16.2 476 499
Total: 1593 1687 67.7 1730 1756

Percentage of the requests served within a certain time (ms)
50% 1730
66% 1733
75% 1741
80% 1753
90% 1756
95% 1756
98% 1756
99% 1756
100% 1756 (longest request)
Repeat above command 3-5 times and save the best reading.

Static Non-KeepAlive test for lighttpd web server
First, reboot the server:
# reboot
Stop Apache web server. Now configure lighttpd and copy /var/www/html/snkpage.html to lighttpd webroot and run the command (from other linux/bsd system):
$ ab -n 1000 -c 5
c) Plot graph using Spreadsheet or gnuplot.

How do I carry out Web server Static KeepAlive test?
Use -k option that enables the HTTP KeepAlive feature using ab test tool. For example:
$ ab -k -n 1000 -c 5
Use the above procedure to create php, fast-cgi and dynmic pages to benchmarking the web server.

Please note that 1000 request is a small number you need to send bigger (i.e. the hits you want to test) requests, for example following command will send 50000 requests :
$ ab -k -n 50000 -c 2
How do I save result as a Comma separated value?
Use -e option that allows to write a comma separated value (CSV) file which contains for each percentage (from 1% to 100%) the time (in milliseconds) it took to serve that percentage of the requests:
$ ab -k -n 50000 -c 2 -e apache2r1.cvs
How do I import result into excel or gnuplot programs so that I can create graphs?
Use above command or -g option as follows:
$ ab -k -n 50000 -c 2 -g apache2r3.txt
Put following files in your webroot (/var/www/html or /var/www/cgi-bin) directory. Use ab command.

Sample test.php file
$command=`perl -v`;
$title = "Perl Version";

print "Content-type: text/html\n\n";
print "<html><head><title>$title</title></head>\n<body>\n\n";

print "

print $command;

print "\n\n</body></html>";
Run ab command as follows:
$ ab -n 3000 -c 5
Sample psql.php (php+mysql) file
$link = mysql_connect("localhost", "USERNAME", "PASSWORD");

$result = mysql_query($query);

while ($line = mysql_fetch_array($result))
foreach ($line as $value)
print "$value\n";


Run ab command as follows:
$ ab -n 1000 -c 5

Setting up a FreeBSD 6.2 Web Server: Proxy Caching (Part 7)

Okay I lied, eAccelerator gives a pretty darn high ROI, but setting up a proxy cache gives a comparable or higher ROI. I chose to use Varnish as my proxy cache.

Once installed, Varnish will keep a cache of all objects requested by internet users (e.g. post-generated PHP pages, CSS, javascripts, images) with the goal of off-loading some work from your web server (remember: we won’t want big Apache to do the work only if it has to). Also Varnish takes full advantage of the OS’s virtual memory and advanced I/O features on FreeBSD 6.x making it the optimal choice for my setup.

There were many confusing instructions on the web about how to configure Varnish. Here are the steps I took to setting up Varnish for a signal machine running both Varnish and the web server:

1) Port install Varnish.

cd /usr/ports/www/varnish/; make install clean
2) Change Apache’s port to 8080 by modifying this line in /usr/local/etc/apache/httpd.conf

Listen 8080
3) Restart Apache

/usr/local/etc/rc.d/apache22 restart
4) Start the Varnish daemon. Substitute the IP below with your machine’s internal network IP address. If you are hosting at home, it is most likely 192.168.0.* but you can run ifconfig to find out what it is.

varnishd -a :80 -b localhost:8080
That’s it! From now, all requests on port 80 should now be routed through the Varnish proxy cache. A proxy cache miss will seemlessly make Apache calls to serve the internet user without the user ever knowing it! A proxy cache hit would not access Apache (and therefore not access MySQL) lessening your machine CPU usage and increasing the speed & efficiency of serving objects to user.

Setting up a FreeBSD 6.2 Web Server: Optimizing PHP (Part 6)

This was by far the easiest step in my optimization process. To optimize PHP, I used the software called eAccelerator. Compared to all of the other steps, this one had the best ROI for me.
When a PHP script is executed, the PHP interpreter will spend some time interpreting the script then compile the interpretations into opcodes for execution. eAccelerator will precompile your PHP code into ready executable opcodes and manage that opcode cache for you. If your PHP script does not change, Apache will directly call the precompiled opcodes (saving interpretation and compilation time).

This is what I did to set it up:
1) Port install eAccelerator
cd /usr/ports/www/eaccelerator; make install clean

2) Inject these lines into /usr/local/etc/php.ini
; eAccelerator Stuff
eaccelerator.allowed_admin_path = "/usr/local/www/apache22/data"

3) Make cache directory writable
mkdir /tmp/eaccelerator
chown www /tmp/eaccelerator
chmod 0700 /tmp/eaccelerator

4) Restart Apache
/usr/local/etc/rc.d/apache22 restart

That’s it! This 10 minute optimization slashed my page generation time by 25%! But if that’s still not fast enough for you, I will show you how to do Proxy Caching next.