Default Local Network IP Addresses for VirtualBox

Default network adapter in VirtualBox is set to Network Address Translation (NAT) within IP address of 10.0.2.x. If we want to use the default IP addresses of your actual local network (e.g. 192.168.x.x) , change the adapter type to Bridged Adapter as shown. Your Virtual Machine will be treated as another server in the local network.


What is debian-sys-maint?

debian-sys-maint, who are you?
A special MySQL user account used by init script to perform certain administrative task.

Where is the login details being stored?
$ sudo ls -ld /etc/mysql/debian.cnf 
-rw------- 1 root root 333 2011-03-19 20:35 /etc/mysql/debian.cnf
And the file is readable by root user only.

Can I remove this account?
You cannot remove this MySQL user from the database otherwise the mysql server will not start.

Can this account be used for other purpose?
Yes and you can use this account login details as a backup user instead of creating another mysql account. Example
$ sudo mysqldump --defaults-file=/etc/mysql/debian.cnf mysql > /tmp/mysql.sql

Uncomplicate Firewall (ufw) Rules for LAMP in Ubuntu Server

-- 0. Check status
$ sudo ufw status 
Status: inactive

-- 1. Enable typical ports for SSH, HTTP(S)
$ sudo ufw allow ssh
$ sudo ufw allow http
$ sudo ufw allow https
$ sudo ufw allow mysql

-- 2. Enable the firewall
$ sudo ufw enable

-- 3. Don't like it, reset to default
$ sudo ufw reset ~
Resetting all rules to installed defaults. Proceed with operation (y|n)? y
Backing up 'user.rules' to '/lib/ufw/user.rules.20111029_214156'
Backing up 'after6.rules' to '/etc/ufw/after6.rules.20111029_214156'
Backing up 'user6.rules' to '/lib/ufw/user6.rules.20111029_214156'
Backing up 'before6.rules' to '/etc/ufw/before6.rules.20111029_214156'
Backing up 'after.rules' to '/etc/ufw/after.rules.20111029_214156'
Backing up 'before.rules' to '/etc/ufw/before.rules.20111029_214156'

Sending Email Through Console

$ echo "foobar" | mail -s "testing" foobar@mailinator.net
The program 'mail' can be found in the following packages:
* heirloom-mailx
* mailutils
Try: apt-get install 

So, I was given two choices. Which one? I ended up picking mailutils because of dependency of Exim.
$ sudo -s
# sudo apt-get update; sudo apt-get upgrade;
# sudo apt-get install mailutils exim4-daemon-light
# dpkg-reconfigure exim4-config
- General type of mail configuration: internet site
- System mail name: foobar
- IP-addresses to listen on for incoming SMTP connections: 127.0.0.1 ; ::1
- Other destinations for which mail is accepted: foobar; localhost.localdomain; localhost
- Domains to relay mail for:
- Machines to relay mail for:
- Keep number of DNS-queries minimal (Dial-on-Demand) : 
- Delivery method for local mail: mbox format in /var/mail
- Split configuration into smaller files: 

To test.
$ exim -bt foobar@mailinator.net

R: dnslookup for foobar@mailinator.net
foobar@mailinator.net
router = dnslookup, transport = remote_smtp
host mailinator.net [66.135.37.96] MX=10
$ echo "foobar" | mail -s "testing" foobar@mailinator.net
$ sudo tail -f /var/log/exim4/mainlog

To use BCC or CC, you must install bsd-mailx package, the default GNU mailutils package does not support this.
$ sudo apt-get install bsd-mailx

Carbon Copy (CC).
$ echo "testing cc email" | mail -s "testing email cc" -c foobar@mailinator.com barfoo@mailinator.com

Blind Carbon Copy (BCC).
$ echo "testing bcc email" | mail -s "testing email bcc" -b foobar@mailinator.com barfoo@mailinator.com

Thanks to mailinator.com, you can check the email inbox at http://barfoo.mailinator.com and http://foobar.mailinator.com.

Send Email From Command Line

Occasionally during development, you'll need to send email to test out certain feature or cron job. Moreover, is nice to have this feature from the command line or console so you can debug and trace any issues.

$ echo "foobar" | mail -s "testing" foobar@mailinator.net
The program 'mail' can be found in the following packages:
* heirloom-mailx
* mailutils
Try: apt-get install 

So, I was given two choices. Which one? I ended up picking GNU Mailutils because of dependency of Exim, which is known to be lightweight and easy to configure.
$ sudo -s
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install mailutils exim4-daemon-light
$ dpkg-reconfigure exim4-config

Exim mailer was configured using following settings.
  • General type of mail configuration: internet site
  • System mail name: foobar
  • IP-addresses to listen on for incoming SMTP connections: 127.0.0.1 ; ::1
  • Other destinations for which mail is accepted: foobar; localhost.localdomain; localhost
  • Domains to relay mail for:
  • Machines to relay mail for:
  • Keep number of DNS-queries minimal (Dial-on-Demand) : 
  • Delivery method for local mail: mbox format in /var/mail
  • Split configuration into smaller files: no

To check whether we've configure Exim correctly.
$ exim -bt foobar@mailinator.net

R: dnslookup for foobar@mailinator.net
foobar@mailinator.net
router = dnslookup, transport = remote_smtp
host mailinator.net [66.135.37.96] MX=10

To send out a sample test email.
$ echo "foobar" | mail -s "testing" foobar@mailinator.net
$ sudo tail -f /var/log/exim4/mainlog

However, GNU Mailutils does not support neither Bind Carbon Copy (BCC) nor Carbon Copy (CC). Hence, we've to install the bsd-mailx package.
$ sudo install apt-get install bsd-mailx

To send a Carbon Copy (CC) email.
$ echo "testing cc email" | mail -s "testing email cc" -c foobar@mailinator.com barfoo@mailinator.com

To send a test Blind Carbon Copy (BCC) email.
$ echo "testing bcc email" | mail -s "testing email bcc" -b foobar@mailinator.com barfoo@mailinator.com

MySQL Silent Truncation

I have been burned twice in the past month by default MySQL behaviours. Before we proceed with these gotchas, let's setup a sample database.

Create a sample test database.
$ mysqladmin -u root -p create test
$ mysql -u root -p test

Data truncation or garbage in NOT necessary garbage out. The price of 12,000 was truncated into 12.00
mysql> create table items(price numeric(12, 2));
Query OK, 0 rows affected (0.07 sec)

mysql> insert into items values('12,000');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from items \G;
************************* 1. row *************************
price: 12.00
1 row in set (0.00 sec)

VARCHAR and TEXT in PostgreSQL

There is not performance between varchar and text datatype in PostgreSQL. The use of varchar and text are interchangeable. To quote the PG doc (bold emphasis by me.),
"Tip: There is no performance difference among these three types, apart from increased storage space when using the blank-padded type, and a few extra CPU cycles to check the length when storing into a length-constrained column. While character(n) has performance advantages in some other database systems, there is no such advantage in PostgreSQL; in fact character(n) is usually the slowest of the three because of its additional storage costs. In most situations text or character varying should be used instead."
Further discussion at Reddit.

PostgreSQL Installation in Ubuntu

It has been a while since I last use PostgreSQL professionally and I really miss it a lot. The newly 9.1 installation really brings back all the memories and it's quite sad that I can't remember how to use psql anymore. To make the situation worse, I am now stuck with the horrors, stupidity, and the numerous WTF of maintaining old legacy applications developed using The Shitty Toy Db (TSTD)* with no referential integrity. All this crap using this TSTD makes me long for PostgreSQL even more.

* To be fair to TSTD, if you configure it correctly, is not that bad.

Step 1 : Installation
$ sudo add-apt-repository ppa:pitti/postgresql
$ sudo apt-get update

$ sudo apt-cache search postgresql-9.1 
postgresql-9.1 - object-relational SQL database, version 9.1 server
postgresql-9.1-dbg - debug symbols for postgresql-9.1
postgresql-client-9.1 - front-end programs for PostgreSQL 9.1
postgresql-contrib-9.1 - additional facilities for PostgreSQL

$ sudo apt-get install postgresql-9.1 postgresql-9.1-dbg postgresql-client-9.1 postgresql-contrib-9.1

Step 2 : Setting up your own database account
$ echo $USER
foobar

$ sudo -u postgres createuser --superuser $USER

$ sudo -u postgres psql 
postgres=# \password foobar
Enter new password: 
Enter it again: 
postgres=# \q

$ createdb $USER
$ psql

Step 3 : Have fun.
Step 4 : Profit ?!

Finding GNU/Linux Distro And Architecture

Dealing with quite a few new servers recently and we can't find the original hardware specification as quoted in the invoice. While we can google for the spec based on the hardware vendor and model, however certain parts of the machine may be upgraded or replaced. To be sure, always double-check the hardware spec. To do this, we need to answer two questions.

1) What is the GNU/Linux distro and architecture of the existing server?
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 11.04
Release: 11.04
Codename: natty

$ uname -a
Linux foobar 2.6.38-11-generic #48-Ubuntu SMP Fri Jul 29 19:02:55 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

2) What is the hardware specification of the server?
console output
$ sudo lshw

GUI output
$ sudo apt-get install lshw-gtk
$ sudo lshw -X

OR
$sudo lshw-gtk

OR (if you are running Ubuntu or you boot the machine using Live CD)
System -> Preferences -> Hardware Lister

Generating MySQL Qeuries

mysql > SELECT Concat('TRUNCATE TABLE ', TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES;
......
2270 rows in set (0.01 sec)

OMFG! WTF?! What have I done??
For a moment I thought I just accidentally truncates 34 databases and 2270 tables. Phew, luckily is just some string output to the console. No databases, tables, and records were harmed.

About add-apt-repository

I was trying to install latest greatest package from a Personal Package Archives (PPA) in an Ubuntu Server installation where the system complained that add-apt-repository command is missing. Did some googling around.

What is add-apt-repository?
"add-apt-repository is a script which adds an external APT repository to either /etc/apt/sources.list or a file in /etc/apt/sources.list.d/."
-- $ man add-apt-repository
Where is add-apt-repository?
$ sudo apt-get install apt-file
$ sudo apt-file update
$ sudo apt-file search add-apt-repository
python-software-properties: /usr/bin/add-apt-repository
python-software-properties: /usr/share/man/man1/add-apt-repository.1.gz

How to install it?
$ sudo apt-get install python-software-properties
$ man add-apt-repository

Removing Personal Package Archives (PPA) Repository

$ sudo apt-file search ppa-purge
ppa-purge: /usr/sbin/ppa-purge
ppa-purge: /usr/share/doc/ppa-purge/copyright
ppa-purge: /usr/share/man/man1/ppa-purge.1.gz

$ sudo apt-get install ppa-purge
$ sudo ppa-purge ppa://repository_name/subdirectory

Further reading.

No Arrow Keys in Vim

From https://github.com/thoughtbot/dotfiles/blob/master/vimrc
" Get off my lawn
nnoremap  :echoe "Use h"
nnoremap  :echoe "Use l"
nnoremap  :echoe "Use k"
nnoremap  :echoe "Use j"

Interesting. Maybe I should put these lines into the dot file to prevent the intern from using the arrow keys?

Reinstall Ubuntu and Update All Packages.

As far as I remember, every major Ubuntu upgrades will fail me in one way or another. This time I accidentally switched off the lappy while upgrading, causing corruption to the filesystem and making it unmountable. Luckily, rescue mode help me to backup all the files before a reinstallation.

Bootable USB live thumb drive.
Since my lappy has no CDROM, I will need to download the ISO and burn it to a thumb drive. Creating a bootable USB thumb drive is done through Unetbootin.

Apt-get Mirror Servers.
It seems that our local Ubuntu update servers are slower compare to our neighbour country, Singapore. On average, I can get 50 - 60 kB/s from .SG server where .MY server only gave me downloading speed of 20 - 30 kB/s. Why ? I have no idea what so ever. Can someone enlighten me on this?

To change the update servers,
$ sudo -s
$ cd /etc/apt
$ sed -i.orig 's/my/sg/' sources.list

Some explanation on the sed command. It basically tell sed
  • to modify the sources.list in place (save in the same file)
  • make backup of the original file with .orig sufffix.
  • substitute my with sg
Further reading on the sed command.

Then we continue with the update and upgrade.
$ apt-get update; apt-get -y upgrade

More steps ahead.

Subversion Keyword Substitution

I don't know when and why this this started but it has become an old habit of mine when I inherit any legacy projects.

Put all $Id$ tag at head of the file after the <?php opening tag. Note that the keyword Id is a substitution for Revision, Date, and Author.
<?php
// $Id$

Set keywords property to all php files
$ svn -R propset svn:keywords "Id" *

Commit the property changes and update local copy
$ svn commit -m "set keyword property" *
$ svn up

See the result
$ cat test.php

<?php
// $Id: test.php 12 2011-08-28 13:09:48Z foobar $

Search and Replace Strings Without Using find and sed

Using replace (utility that came with mysql)
$ sudo apt-get install mysql
$ replace foo bar *.php

Using rpl
$sudo apt-get install rpl
$ rpl -R foo bar *.php

Declaring CONSTANT in PHP

Instead of checking and declaring constant in this way
<?php
if ( ! defined('FOOBAR') ) define('FOOBAR', '123');

We can rewrite it as
<?php
defined('FOOBAR') or define('FOOOBAR', '123');

unexpected T_ECHO

Having extra space between <? php gave you all soft of unhelpful error message.

foobar.php
< ? php
echo '123';

$ php -f foobar.php

php -f t.php 
PHP Parse error: syntax error, unexpected T_ECHO in /tmp/foobar.php on line 3

Difference Between require_once And require

Really caught me by surprise this morning. The poor intern had to manually click the item one by one.

foobar.php
<?php
foreach ( range(0, 4) as $no )
{
require_once 'a.php';
require 'b.php';
}

a.php
<?php echo "a:$no\n"; ?>

b.php
<?php echo "a:$no\n"; ?>

$ php -f foobar.php
a:0 <----- notice that a.php only include ONCE
b:0
b:1
b:2
b:3
b:4

Split a String Into Array Without Delimiter

Following advice from StackOverflow.
$ php -a

php > print_r(str_split('foobar', 1));
Array
(
[0] => f
[1] => o
[2] => o
[3] => b
[4] => a
[5] => r
)

Tidy Up XML File

Some googling around, between tidy and xml_pp, the later format a better looking XML file.
$ sudo apt-get install xml-twig-tools
$ xml_pp foo.xml > bar.xml

PHP's DateTime between 5.2 and 5.3

Is very annoying to have different PHP version between development, staging, live and client machine. Regardless what, must force everyone to upgrade to version 5.3.x.

Interval
$datetime = new DateTime();
$datetime->add(new DateInterval('P1D')); // 5.3
$datetime->modify('+1 day'); // 5.2

Timestamp
$datetime = new DateTime();
$datetime->getTimestamp(); // 5.3
$datetime->format('U'); // 5.2

Doctrine 2.1.0 ORM Installation

$ sudo pear install pear.doctrine-project.org/DoctrineORM-2.1.0
downloading DoctrineORM-2.1.0.tgz ...
Starting to download DoctrineORM-2.1.0.tgz (211,677 bytes)
.............................................done: 211,677 bytes
downloading DoctrineSymfonyYaml-2.0.6.tgz ...
Starting to download DoctrineSymfonyYaml-2.0.6.tgz (22,204 bytes)
...done: 22,204 bytes
install ok: channel://pear.doctrine-project.org/DoctrineSymfonyYaml-2.0.6
install ok: channel://pear.doctrine-project.org/DoctrineORM-2.1.0

$ doctrine
Doctrine Command Line Interface version 2.1.0
....

How to Find the Last Day of a Month in PHP

Start PHP in interactive mode.
$ php -a

Find the last day using the current UNIX timestamp.

The Procedural Style
php > echo date('t', time());
31

The Object-Oriented Style
php > $date = new DateTime();
php > echo $date->format('t');
31

Find the last day using date.

The Procedural Style
php > echo date('t', mktime(0, 0, 0, 7, 1, 2011));
31
php > echo date('t', mktime(0, 0, 0, 2, 1, 2011));
28
php > echo date('t', mktime(0, 0, 0, 2, 1, 2012));
29

The Object-Oriented Style
php > $date = new DateTime();
php > echo $date->format('t');
31
php > $date = new DateTime('2011-02-01');
php > echo $date->format('t');
28
php > $date = new DateTime('2012-02-01');
php > echo $date->format('t');
29

Symfony 1.x PHP Framework Installation and Setup

1. Download Symfony framework from http://symfony.com/download

2. Extract the tarball to /var/www/symfony

3. Point your browser to http://localhost/symfony/web/config.php

4. Fix the directory permission
$ cd /var/www/symfony
$ sudo chown -R www-data:www-data cache logs

5. Refresh step 3. Adjust the all the outstanding issues

6. Edit /etc/php5/apache2/php.ini and set these parameters
date.timezone = Asia/Kuala_Lumpur
short_open_tag = Off

7. Install the missing php's intl module
sudo apt-get install php5-intl

8. Restart the Apache2 webserver
sudo /etc/init.d/apache2 restart

9. Refresh step 3. No warning, click Configure your Symfony Application online

10. Setup database. Fill in all your database connection details.

11. Setup global secret key. Leave it as it.

12. Copy, paste, and save the configuration detail into /var/www/symfony/app/config/parameters.ini

13. Click Go to the Welcome Page >

14. Click RUN THE DEMO and select Hello World >

15. Browse. Click. Read. Browse. Click. Read. OMFG!

How to Properly Set External Definition Using Subversion

$ svn propset svn:externals "local_folder http://remoteip/project_name" .
$ svn up
$ svn commit -m "Add external library link"

Two important points,
  1. You must quote the property value
  2. The dot (.), which is referring to the local directory, at the end of the command IS NECESSARY