Wednesday, December 17, 2008

How To Configure Web Access To Subversion Repositories Using Apache


This how to is going to describe the steps to get the mod_dav_svn module to work in an Apache web server. First I'll assume that we don't have Apache and Subversion installed on our FreeBSD box, in a second part I'll explain how to add the module using our current installation.

First we have to install our Apache 2.0.x with Berkeley DB support (because Subversion will use Berkeley DB to save the repositories). To do this we have to go to the ports dir and do this:

box# cd /usr/ports/www/apache20/
box# make -DWITH_BDB4 install clean
some installation steps...

Add apache ability to start automatically at boot time:

box# echo 'apache2_enable="YES"' >> /etc/rc.conf

After we have apache20 installed with bdb support, we'll have to install Subversion:

box# cd /usr/ports/devel/subversion
box# make -DWITH_MOD_DAV_SVN install clean
some installation steps...

After installation we'll have to ensure that mod_dav_svn module was properly installed on apache.

box# cat /usr/local/etc/apache2/httpd.conf | grep svn

LoadModule dav_svn_module libexec/apache2/mod_dav_svn.so
LoadModule authz_svn_module libexec/apache2/mod_authz_svn.so

We have apache with mod_dav_svn module installed properly. At this point we can create a repository. This will help us to test our instalation:

box# mkdir /usr/home/svn
box# mkdir /usr/home/svn/repos
box# svnadmin create /usr/home/svn/repos/test

Then we have to create the files that are going to be used to authenticate the users.

box# mkdir /usr/home/svn/access
box# cd /usr/home/svn/access
box# htpasswd -cm users root
password:****
box# htpasswd -m users viewer
password:*****

box# vi control

[test:/]
root = rw
viewer = r.


At this point we have apache with bdb support, subversion with mod_dav_svn module installed, our repository created, the users and the control to our repository. Now we will configure apache to read the repositories:

box# cd /usr/local/etc/apache2/Includes/
box# cat svn.conf


DAV svn
SVNParentPath /usr/home/svn/repos
SVNIndexXSLT "http://svn.example.com/svnindex.xsl"
AuthzSVNAccessFile /usr/home/svn/access/control
# anonymous first
Satisfy Any
Require valid-user
# authenticating them valid ones
AuthType Basic
AuthName "Subversion Repositories at example.com"
AuthUserFile /usr/home/svn/access/users

Apache will read all the files that are under the Includes directory, so our svn.conf will be loaded when apache starts, note that we are loading svnindex.xsl that is the file where the transformations are done, if you would like to give to your repository some look and feel work these file will be the appropiate. The file skeletons are under /usr/local/share/subversion/xslt/ directory, there are two files, one .xsl and another .css. Copy these files to your document root. I have a virtual server called svn.example.com in my machine. I have all my virtual servers under /usr/local/www/pages, so I have svn.example.com directory and I've configured that virtual server in /usr/local/etc/apache2/httpd.conf.

NameVirtualHost *:80

ServerAdmin ecruz@example.com
ServerName svn.example.com
DocumentRoot /usr/local/www/pages/svn.example.com
CustomLog /var/log/svn.example.com-access_log common

Restart the web server:

/usr/local/etc/rc.d/apache2.sh restart

If all went ok, we have our web server working properly, to test it, open in your Firefox or whatever browser and go to http://svn.example.com/svn/repos/test. It will ask you for the credentials, so use root or viewer. It must display the test repository at revision 0. I'll suggest to install TortoiseSVN on Windows boxes to get access to the repositories.

Now, as a plus, we will configure an alert in our subversion test repository to send a notification when a commit was done. To do this we will have to create an executable file under the hooks directory:

box# cd /usr/home/svn/repos/test/hooks/
box# cat post-commit

[code]
#!/usr/local/bin/php

[/code]

To get this to work with your current installation you have to change only the subversion installation step:

box# cd /usr/ports/devel/subversion
box# make deinstall
box# make -DWITH_MOD_DAV_SVN -DWITHOUT_BDB4 install clean

Ok, this is the end of this howto, any improvements are welcome. Regards!

Thursday, November 06, 2008

nohup Execute Commands After You Exit From a Shell Prompt

Most of the time you login into remote server via ssh. If you start a shell script or command and you exit (abort remote connection), the process / command will get killed. Sometime job or command takes a long time. If you are not sure when the job will finish, then it is better to leave job running in background. However, if you logout the system, the job will be stopped. What do you do?

nohup command

Answer is simple, use nohup utility which allows to run command./process or shell script that can continue running in the background after you log out from a shell:

nohup Syntax:

nohup command-name &

Where,

  • command-name : is name of shell script or command name. You can pass argument to command or a shell script.
  • & : nohup does not automatically put the command it runs in the background; you must do that explicitly, by ending the command line with an & symbol.

nohup command examples

1) Login to remote server
$ ssh user@remote.server.com
2) Execute script called pullftp.sh
# nohup pullftp.sh &
Type exit or press CTRL + D exit from remote server.
# exit
3) Find all programs and scripts with setuid bit set on, enter:
# nohup find / -xdev -type f -perm +u=s -print > out.txt &
Type exit or press CTRL + D exit from remote server.
# exit
Please note that nohup does not change the scheduling priority of COMMAND; use nice for that:
# nohup nice -n -5 ls / > out.txt &
As you can see nohup keep processes running after you exit from a shell. Read man page of nohup and nice command for more information. Please note that nohup is almost available on Solaris/BSD/Linux/UNIX variant.

Update:
# 1: As pointed out by Jason you can use at command to queue a job for later execution. For example, you can run pullftp.sh script to queue (one minute) later execution
$ echo "pullftp.sh" | at now + 1 minute
# 2: You can also use screen command for same. Brock pointed out disown shell internal command for same purpose. Here is how you can try it out:
$ pullftp.sh &
$ disown -h
$ exit

According to bash man page:

By default, removes each JOBSPEC argument from the table of active jobs. If the -h option is given, the job is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP. The -a option, when JOBSPEC is not supplied, means to remove all jobs from the job table; the -r option means to remove only running jobs.

Friday, October 31, 2008

autostart apache during boot

i just finished my apache, php, mysql installation for my new server.  i used Centos 5.1. Those not started when i reboot my server. Oh..i forgot to make it autostart during boot time. 

Here the steps to auto run apache or mysql during the boot time..

run command runlevel to check your current Centos run level

Running runlevel command on my centos linux machines displays default run level as 5.You must be wondering what runlevel has to do with by autostarting apache server. There is reason for that Linux uses different run levels to boot and you should know default runlevel where you would like to configure apache to autostart during boot.

Next you have to use magic command called chkconfig on fedora to list the apache (httpd) services runlevel:

[root@node12 ~]# chkconfig --list httpd

httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off

In chkconfig output off means apache (httpd) service is set with no autostart for associated runlevels. Since my default runlevel is 5 , I need to set apache to autostart in runlevel 5 using chkconfig. Here is how you can turn apache autostart for your default run level :

[root@node12 ~]# chkconfig --level 5 httpd on


If your default run level is 3 then you should use 3 in above command. You can also run 

 [root@node12 ~]# chkconfig --level 235 httpd on

to make ur apache run on level 2,3 and 5. 

Now to check if autostart is set as on during boot


Run checkconfig again :

[root@node12 ~]# chkconfig --list httpd

httpd 0:off 1:off 2:off 3:off 4:off 5:on 6:off

that's all..Centos your life!! 




configure: error: C compiler cannot create executables

Today I have tried to compile a software in a Linux machine, when I run

./configure

I got

checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for gawk... no checking for mawk... mawk checking whether make sets $(MAKE)... yes checking for multicast... checking for gcc... no checking for cc... no checking for cl.exe... no configure: error: no acceptable C compiler found in $PATH See `config.log' for more details. 

Then I installed gcc with:

apt-get install gcc 

for Ubuntu and for Centos i used

yum install gcc 

and try again, this time I got:

and try again, this time I got:

checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for gawk... no checking for mawk... mawk checking whether make sets $(MAKE)... yes checking for multicast... checking for gcc... gcc checking for C compiler default output file name... configure: error: C compiler cannot create executables See `config.log' for more details. 

To solve this I had to install g++

apt-get install g++

And then when I tried again it worked, so to compile software with Linux it seems that you mostly need to install both

gcc and g++

Update: Thanks to Thadeu Penna a friend of the blog for this tip.

using

apt-get install build-essential

Will install all the basic tools for developing in Debian and I know it also works for Ubuntu.

enable and disable SElinux

Important

Changes you make to files while SELinux is disabled may give them an unexpected security label, and new files will not have a label. You may need to relabel part or all of the file system after re-enabling SELinux.

From the command line, you can edit the /etc/sysconfig/selinux file. This file is a symlink to/etc/selinux/config. The configuration file is self-explanatory. Changing the value of SELINUX orSELINUXTYPE changes the state of SELinux and the name of the policy to be used the next time the system boots.

[root@host2a ~]# cat /etc/sysconfig/selinux # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: #       enforcing - SELinux security policy is enforced. #       permissive - SELinux prints warnings instead of enforcing. #       disabled - SELinux is fully disabled. SELINUX=permissive # SELINUXTYPE= type of policy in use. Possible values are: #       targeted - Only targeted network daemons are protected. #       strict - Full SELinux protection. SELINUXTYPE=targeted  # SETLOCALDEFS= Check local definition changes SETLOCALDEFS=0 
Changing the Mode of SELinux Using the GUI

Use the following procedure to change the mode of SELinux using the GUI.

Note

You need administrator privileges to perform this procedure.

  1. On the System menu, point to Administration and then click Security Level and Firewall to display the Security Level Configuration dialog box.

  2. Click the SELinux tab.

  3. In the SELinux Setting select either DisabledEnforcing or Permissive, and then click OK.

  4. If you changed from Enabled to Disabled or vice versa, you need to restart the machine for the change to take effect.

Changes made using this dialog box are immediately reflected in /etc/sysconfig/selinux.

Configure PHP connection to Oracle DB – the RPM way

I have CentOS 4.4 box which I want to connect to Oracle DB 10g via PHP
There are 2 way to configure PHP to connect to Oracle DB using OCI:
A. Use PHP RPMs (which included all php module in RPM package) but nowadays oci8 module no longer provider by CentOS and you might use older version of PHP - easiest and quickest way
B. Use current version of PHP and enable oci8 via PEAR. You will get current PHP version with oci8 enable but still in RPM way

Lets begin

A. Use PHP RPMs packages
1. Install Apache if not installed
CODE:
# yum install httpd


2. Download Oracle Client Software -- if you are using GUI
or download Oracle InstantClient BasicLite (the rpm version) -- I choose this and install it.
to get latest version download it from http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html
CODE:
# rpm –ivh oracle-instantclient-basiclite-*.rpm

my copy of Oracle Instant Client BasicLite is here
http://www.am3n.profusehost.net/phpoci/oracle-instantclient-basic-10.2.0.3-1.i386.rpm

3. Install PHP and makesure you installed php-oci8 module, other modules you can install it if you like
CODE:
# rpm -ivh php-5*.rpm php-oci8-*.rpm php-pear-*.rpm

I am not using CentOS version because it's not provide oci8 module. But I am using PHP from Miracle Linux - Asianux which also look-like Redhat derivatives distro. They provide complete PHP module including oci8.
Download it from my mirror here.
http://www.am3n.profusehost.net/phprh4/

Info about Miracle Linux - Asianux
http://en.wikipedia.org/wiki/Miracle_Linux
Complete PHP modules from Miracle Linux
http://www.miraclelinux.com/update/linux/list.php?errata_id=249

4. Create local variable to connect to Oracle, for NLS_LANG you can set with your locale.
CODE:

# vi /etc/profiles
LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client/lib
export LD_LIBRARY_PATH
NLS_LANG=AMERICAN_AMERICA.UTF8
export NLS_LANG


5. Update linux Library thingy... (locate the oracle library if you use differrent version)
CODE:
# echo /usr/lib/oracle/10.2.0.3/client/bin/ >> /etc/ld.so.conf
# echo /usr/lib/oracle/10.2.0.3/client/lib/ >> /etc/ld.so.conf
# ldconfig
# cd /usr/lib/oracle/10.2.0.3/client/lib/
# ln -s libclntsh.so.10.1 libclntsh.so
# ln -s libocci.so.10.1 libocci.so


6. (Re-)Start the Apache
CODE:
# service httpd restart


I have CentOS 4.4 box which I want to connect to Oracle DB 10g via PHP
There are 2 way to configure PHP to connect to Oracle DB using OCI:
A. Use PHP RPMs (which included all php module in RPM package) but nowadays oci8 module no longer provider by CentOS and you might use older version of PHP - easiest and quickest way
B. Use current version of PHP and enable oci8 via PEAR. You will get current PHP version with oci8 enable but still in RPM way

Lets begin

A. Use PHP RPMs packages
1. Install Apache if not installed
CODE:
# yum install httpd


2. Download Oracle Client Software -- if you are using GUI
or download Oracle InstantClient BasicLite (the rpm version) -- I choose this and install it.
to get latest version download it from http://www.oracle.com/technology/tech/oci/instantclient/instantcl
ient.html
CODE:
# rpm –ivh oracle-instantclient-basiclite-*.rpm

my copy of Oracle Instant Client BasicLite is here
http://www.am3n.profusehost.net/phpoci/oracle-instantclient-basic
-10.2.0.3-1.i386.rpm

3. Install PHP and makesure you installed php-oci8 module, other modules you can install it if you like
CODE:
# rpm -ivh php-5*.rpm php-oci8-*.rpm php-pear-*.rpm

I am not using CentOS version because it's not provide oci8 module. But I am using PHP from Miracle Linux - Asianux which also look-like Redhat derivatives distro. They provide complete PHP module including oci8.
Download it from my mirror here.
http://www.am3n.profusehost.net/phprh4/

Info about Miracle Linux - Asianux
http://en.wikipedia.org/wiki/Miracle_Linux
Complete PHP modules from Miracle Linux
http://www.miraclelinux.com/update/linux/list.php?errata_id=249

4. Create local variable to connect to Oracle, for NLS_LANG you can set with your locale.
CODE:

# vi /etc/profiles
LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.3/client/lib
export LD_LIBRARY_PATH
NLS_LANG=AMERICAN_AMERICA.UTF8
export NLS_LANG


5. Update linux Library thingy... (locate the oracle library if you use differrent version)
CODE:
# echo /usr/lib/oracle/10.2.0.3/client/bin/ >> /etc/ld.so.conf
# echo /usr/lib/oracle/10.2.0.3/client/lib/ >> /etc/ld.so.conf
# ldconfig
# cd /usr/lib/oracle/10.2.0.3/client/lib/
# ln -s libclntsh.so.10.1 libclntsh.so
# ln -s libocci.so.10.1 libocci.so


6. (Re-)Start the Apache
CODE:
# service httpd restart



B. Use your current PHP version from CentOS
If you already install your PHP and don't want to replace it with older version and/or your current version of PHP didn't provide php-oci8 packages you can install it using the following steps
This how to is modification of PHP-OCI8 in Ubuntu Forum
http://www.ubuntuforums.org/archive/index.php/t-92528.html

1. Install Oracle InstantClient
download it from http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html
CODE:
# rpm -ivh oracle-instantclient-basic-10.2.0.3-1.i386.rpm
# rpm -ivh oracle-instantclient-devel-10.2.0.3-1.i386.rpm

My copy is here
http://www.am3n.profusehost.net/phpoci/oracle-instantclient-basiclite-10.2.0.3-1.i386.rpm
http://www.am3n.profusehost.net/phpoci/oracle-instantclient-devel-10.2.0.3-1.i386.rpm

2. Configure linux library thingie...
CODE:
# echo /usr/lib/oracle/10.2.0.3/client/bin/ >> /etc/ld.so.conf
# echo /usr/lib/oracle/10.2.0.3/client/lib/ >> /etc/ld.so.conf

# ldconfig

3. Install oci8 via pear
Make sure you already install php-devel package (and have upgrade to latest version)

CODE:
# cd /usr/local/src
# pear download oci8
# tar xzf oci8-1.2.3.tgz
# cd oci8-1.2.3
# phpize
# ./configure --with-oci8=shared,instantclient,/usr/lib/oracle/10.2.0.3/client/lib/
# make
# make install

My copy of oci8 is here
http://www.am3n.profusehost.net/phpoci/oci8-1.2.3.tgz

4. Enable oci8
CODE:
# vi /etc/php.d/oci8.ini
; Enable oci8 extention module
extension=oci8.so


5. (Re-)Start the Apache
CODE:
# service httpd restart




Just want to make sure if your php is already configure with oci8 module create a php file with phpinfo() function
Create phpinfo file
CODE:
# vi /var/www/html/phpinfo.php


View phpinfo. http://yourserver/phpinfo.php
You should see something like this
CODE:

oci8
OCI8 Support enabled
Revision $Revision: 1.257.2.8 $
Active Persistent Links 0
Active Links 0
Oracle Version 10.1
Compile-time
ORACLE_HOME /opt/oracle/product/10.1.0
Libraries Used -Wl,-rpath,/opt/oracle/product/10.1.0/lib -
L/opt/oracle/product/10.1.0/lib -lclntsh
Temporary Lob support enabled
Collections support enabled

nstalling PHP and the Oracle 10g Instant Client for Linux and Windows

Updated for PHP 5.1.2


Author: Christopher Jones, Consulting Technical Staff, Oracle Corporation

Updated: January 2006

Oracle 10g Instant Client (free download available) is the easiest way for PHP to connect to a remote Oracle database, requiring installation of only three libraries.

The Instant Client libraries used by PHP access Oracle's current API, called OCI8. (This C interface takes its name from being first introduced in Oracle8.) PHP Oracle 8 Functions can call Oracle 8.1.7, 9.x, or 10.x directly, or optional abstraction classes like PEAR MDB2 and ADOdb can be used for convenience.

The older PHP "oracle" extension can also be used with Instant Client but it calls a deprecated Oracle API. New development with this extension is not recommended by the PHP community or by Oracle.

To use Instant Client with PHP 4 or 5 on Apache, follow the steps below. (See this section for details about 5.1.2 and its refactored OCI8 extension.) An existing Oracle database is needed; Instant Client does not include one.

Typically the database will be on another machine. If the database is local then Oracle components will generally already be available and Instant Client is not required.

Software Requirements:

SoftwareNotes
Oracle Instant ClientDownload the "Instant Client Package - Basic." On Linux, also download the "Instant Client Package - SDK."
Apache HTTPD ServerThe PHP community still recommends Apache 1.3
PHP - PHP Hypertext ProcessorVersion 4.3 or later

Enabling the PHP OCI8 Extension on Windows

The Instant Client binaries complement PHP's prebuilt binaries for Windows.

  1. Download the PHP binary zip file (not the installer build) and Apache. Install them following Installation on Windows Systems in the PHP Manual. OTN's PHP Developer Center contains links to useful background material such as "Installing Oracle, PHP, and Apache on Windows 2000/XP," which covers installation of a traditional, full Oracle 10g footprint (which is not required with Instant Client).

    Check that PHP is working before continuing. At this stage Oracle support is not enabled.

  2. Download the Instant Client Basic package for Windows from the Instant Client page on OTN. The zip file is about 30MB in size.

  3. Create a subdirectory (e.g., c:\instantclient10_1) and copy these libraries from the zip file:

    • oraociei10.dll
    • orannzsbb10.dll
    • oci.dll

    Collectively these three files are about 80MB in size.

    To use PHP's older "oracle" extension (enabled with "extension=php_oracle.dll" in php.ini), copy ociw32.dll instead of oci.dll.

  4. Edit the environment and add c:\instantclient10_1 to PATH before any other Oracle directories.

    For example, on Windows 2000, follow Start -> Settings -> Control Panel -> System -> Advanced -> Environment Variables and edit PATH in the System variables list.

    If a tnsnames.ora file is used to define Oracle Net service names, copy tnsnames.ora to c:\instantclient10_1 and set the user environment variable TNS_ADMIN to c:\instantclient10_1. A default service name can optionally be set in the user environment variable LOCAL.

    Set necessary Oracle globalization language environment variables such as NLS_LANG. If nothing is set, a default local environment will be assumed. See An Overview on Globalizing Oracle PHP Applications for more details.

    Unset unnecessary Oracle variables such as ORACLE_HOME and ORACLE_SID.

  5. Edit php.ini and uncomment the OCI8 extension:

    extension=php_oci8.dll 

    Set the extension_dir directive to the full PHP extension DLL path. In PHP 4 the DLLs are in the "extensions" sub-directory of the PHP software. In PHP 5 they are in "ext".

  6. Restart Apache.

To check the extension is configured, create a simple PHP script phpinfo.php where the web server can read it.

 

Load the script into a browser using an "http://" URL. The browser page should contain an "oci8" section saying "OCI8 Support enabled".

Enabling the PHP OCI8 Extension on Linux

To add Oracle connectivity on Linux, PHP needs to be recompiled.

The PHP Developer Center contains links to useful background material such as Installing Oracle, PHP, and Apache on Linux, which covers installation of a traditional, full Oracle 10g footprint (which is not required with Instant Client).

  1. Download and install Apache. For example, to install it in your home directory:
    cd apache_1.3.31 ./configure --enable-module=so --prefix=$HOME/apache --with-port=8888 make make install 

    Edit $HOME/apache/conf/httpd.conf and add:

    AddType application/x-httpd-php        .php AddType application/x-httpd-php-source .phps 
  2. Download PHP and untar it.
  3. Download the Basic and the SDK Instant Client packages from the Instant Client page on OTN. Collectively the two RPMs are about 30MB in size.
  4. Install the RPMs as the root user.
    rpm -Uvh oracle-instantclient-basic-10.1.0.3-1.i386.rpm rpm -Uvh oracle-instantclient-devel-10.1.0.3-1.i386.rpm 

    The first RPM puts the Oracle libraries in /usr/lib/oracle/10.1.0.3/client/lib and the second creates headers in /usr/include/oracle/10.1.0.3/client

  5. Backup and then apply this patch to PHP's ext/oci8/config.m4. The patch line numbers are based on PHP 4.3.9. This patch will not be necessary when PHP bug 31084 is fixed, most likely in PHP 4.3.11 and 5.0.4.

    If you are using PHP 4.3.9 or 4.3.10 you can save the patch to a file, e.g. php_oci8ic_buildpatch, and install it using:

    patch -u config.m4 php_oci8ic_buildpatch 

    The patch creates a new PHP configuration parameter: --with-oci8-instant-client[=DIR]. On Linux, by default, it uses the latest version of the Instant Client installed from the RPMs. A directory to the Oracle libraries can be specified to use a different version. In either case, the correct SDK headers will automatically be used.

    The new parameter is mutally exclusive with the existing --with-oci8 parameter.

    For reference: on non-Linux platforms, the Instant Client package is unzipped into a directory of your choice. The --with-oci8-instant-client parameter will need this directory explicitly specified; for example, --with-oci8-instant-client=/home/instantclient10_1. The Instant Client SDK should unzipped to the same directory as the basic package so the subdirectory of header files can be located by the revised configuration script.

  6. Rebuild the "configure" script in the top-level PHP directory.
    cd php-4.3.9 rm -rf autom4te.cache config.cache ./buildconf --force 
  7. Run configure with the new option. This example uses Apache installed in the home directory.
       ./configure \       --with-oci8-instant-client \       --prefix=$HOME/php --with-apxs=$HOME/apache/bin/apxs \       --enable-sigchild --with-config-file-path=$HOME/apache/conf 
  8. Rebuild PHP.
    make make install 
  9. Copy the PHP configuration to the location given by --with-config-file-path
    cp php.ini-recommended $HOME/apache/conf/php.ini 
  10. Set LD_LIBRARY_PATH to /usr/lib/oracle/10.1.0.3/client/lib and restart Apache.

    If a tnsnames.ora file is used to define Oracle Net service names, set TNS_ADMIN to the directory containing the file.

    It is important to set all Oracle environment variables before starting Apache. A script helps do that:

    #!/bin/sh  APACHEHOME=/home/apache  LD_LIBRARY_PATH=/usr/lib/oracle/10.1.0.3/client/lib:${LD_LIBRARY_PATH} TNS_ADMIN=/home export LD_LIBRARY_PATH TNS_ADMIN  echo Starting Apache  $APACHEHOME/apachectl start 
To confirm the extension is configured, create a simple PHP script phpinfo.php where the web server can read it.
 

Load the script into a browser using a URL similar to "http://localhost:8888//phpinfo.php". The browser page should contain an "oci8" section saying "OCI8 Support enabled".

Connecting to Oracle

Oracle connection information is passed to OCILogon() to create a connection. Tools linked with Instant Client are always "remote" from any database server and an Oracle Net connection identifier must be used along with a username and password. The connection information is likely to be well known for established Oracle databases. With new systems the information is given by the Oracle installation program when the database is set up. The installer should have configured Oracle Net and created a service name.

In new databases the demonstration schemas such as the HR user may need to be unlocked and given a password. This may also be done in SQL*Plus by connecting as the SYSTEM user and executing the statement:

ALTER USER username IDENTIFIED BY new_password ACCOUNT UNLOCK; 
There are several ways to pass the connection information to PHP. This first example uses Oracle 10g's Easy Connect syntax to connect to the HR schema in theMYDB database service running on mymachine. No tnsnames.ora or other Oracle Network file is needed:
$c = OCILogon('hr', 'hr_password', '//mymachine.mydomain/MYDB'); 

See Oracle's Using the Easy Connect Naming Method documentation for the Easy Connect syntax.

Alternatively, if /home/tnsnames.ora contains:
MYDB =  (DESCRIPTION =    (ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.mydomain)(PORT = 1521))    (CONNECT_DATA =       (SERVER = DEDICATED)       (SERVICE_NAME = MYDB)     )   ) 

and the TNS_ADMIN environment variable was set to /home (before starting Apache), then the connection string could be:

$c = OCILogon('hr', 'hr_password', 'MYDB');        
If the environment variable LOCAL (on Windows) or TWO_TASK (on Linux) was set to MYDB then a connection to MYDB could also be made with:
$c = OCILogon('hr', 'hr_password'); 

Using Oracle

When the basic connection is working, try out a simple script, testoci.php. Modify the connection details to suit your database and load it in a browser. This example lists all tables owned by the user HR:

\n";  }   OCILogoff($conn);   ?> 
Troubleshooting

The Oracle PHP Troubleshooting FAQ contains helpful information on connecting to Oracle.

Oracle's SQL*Plus command line tool can be downloaded from the Instant Client page to help resolve environment and connection problems. Also see the SQL*Plus Instant Client Release Notes.

Check the environment used by SQL*Plus is the same as shown by phpinfo.php.

Windows Help

If the phpinfo.php script does not produce an "oci8" section saying "OCI8 Support enabled", verify that "extension=php_oci8.dll" is uncommented in php.ini.

If PATH is set incorrectly or the Oracle libraries cannot be found, starting Apache will give an alert: "The dynamic link library OCI.dll could not be found in the specified path." The Environment section of the phpinfo() page will show the values of PATH and the Oracle variables actually being used by PHP.

If php.ini's extension_dir directive is not correct, Apache startup will give an alert: "PHP Startup: Unable to load dynamic library php_oci8.dll."

Linux Help

Carefully check config.m4 was patched correctly. If "configure" fails, check the config.log file. Revert config.m4, remove caches files, run ./buildconf --force and configure, and verify that the problems are related to the changes made.

Make sure the timestamp on "configure" is current. Remove any cache files and rebuild it if necessary.

Set all required Oracle environment variables in the shell that starts Apache.

For PHP 5.1.2 and Later

The "re-factored" OCI8 extension introduces new syntax for Instant Client support. The re-factored extension was first included in PHP 5.1.2. It is also available frompecl.php.net/package/oci8 and pecl4win.php.net/ext.php/php_oci8.dll for earlier versions of PHP.

If you have installed the Instant Client RPMs as described in this Technical Note, configure PHP with:

./configure \     --with-oci8=instantclient,/usr/lib/oracle/10.1.0.3/client/lib \     --prefix=$HOME/php --with-apxs=$HOME/apache/bin/apxs \     --enable-sigchild --with-config-file-path=$HOME/apache/conf 
If you are using the Instant Client Basic and SDK zip files then change the --with-oci8 option to the unzipped directory, e.g:
--with-oci8=instantclient,$HOME/instantclient10_1  
To tell if you have the re-factored extension, check the output of phpinfo(). It will show seven directives with an "oci8." prefix. These are not present in the previous incarnation.

Conclusion

I hope this article has been helpful. Questions and suggestions can be posted on the OTN Instant Client or PHP forums.

Thursday, October 23, 2008

Disable SELinux on CENTOS 5

To check and see if SELINUX (secure linux) is installed and running on your Red Hat ES 5 (CentOS 5, etc) server, use a text editor to open /etc/selinux/config:

vi /etc/selinux/config

Inside you should see a line that says

SELINUX=*some value*

Where *some value* is either enforcingpermissive or disabled. To shut SELINUX off, set the variable todisabled. To receive a set of errors to see what services would be affected if SELINUX was running, set it toperimissive. If you are sure all your services, daemons and everything else is set up with correct SELINUXpermissions, you can set it to enforcing.

If you're getting an error after compiling and installing an Oracle OCI8 module for PHP you might want to setSELINUX to permissive or disabled until you are able to resolve the permission problem.

If you have to change the setting you should reboot the server to make sure the change takes effect system wide.

Wednesday, October 22, 2008

install apache, mysql and php on centos

Below are the steps to install LAMP (Apache, PHP and MySQL in Linux) using Yum:-

  • Go to CentOS and download a copy of CentOS Linux and install it (i’ll not go thru the how to install CentOS with you here)
  • Once your CentOS is installed. Open a terminal (if you are using X-Window), and type yum install httpd and follow on screen instruction to install apache web server
  • Once apache web server has been installed, type yum install php
  • Once php installed try to install it's extension type yum install php-common php-gd php-mcrypt php-memchache php-mhash php-mysql php-xml
  • Once PHP installed successfully, type yum install mysql-server mysql
  • Once everything finish, type service httpd start to start your apache web server, screen will show you if web server service successfully started
  • type service mysqld start to start your mysql server
  • Once both services is running, you can point your browser to http://localhost and you should see a welcome page from CentOS
  • If you see that welcome page, you just installed everything successfull.
  • To test if php is running, go to /var/www/html and create an index.php file with the content below

    and refresh your browser again. If you see a purple PHP information page showing all the php configuration variables, then php is running now.
  • Congratulation, you just successfully installed LAMP in your machine.

Tuesday, September 23, 2008

Using ADOdb with PHP and Oracle: an advanced tutorial

1. Introduction

Oracle is the most popular commercial database used with PHP. There are many ways of accessing Oracle databases in PHP. These include:

  • The oracle extension
  • The oci8 extension
  • PEAR DB library
  • ADOdb library

The wide range of choices is confusing to someone just starting with Oracle and PHP. I will briefly summarize the differences, and show you the advantages of using ADOdb.

First we have the C extensions which provide low-level access to Oracle functionality. These C extensions are precompiled into PHP, or linked in dynamically when the web server starts up. Just in case you need it, here’s a guide to installing Oracle and PHP on Linux.

Oracle extension Designed for Oracle 7 or earlier. This is obsolete.

Here is an example of using the oci8 extension to query the emp table of the scott schema with bind parameters:

$conn = OCILogon("scott","tiger", $tnsName);

$stmt = OCIParse($conn,"select * from emp where empno > :emp order by empno");
$emp = 7900;
OCIBindByName($stmt, ':emp', $emp);
$ok = OCIExecute($stmt);
while (OCIFetchInto($stmt,$arr)) {
print_r($arr);
echo "
";
}

This generates the following output:

Array ( [0] => 7902 [1] => FORD [2] => ANALYST [3] => 7566 [4] => 03/DEC/81 [5] => 3000 [7] => 20 )


Array ( [0] => 7934 [1] => MILLER [2] => CLERK [3] => 7782 [4] => 23/JAN/82 [5] => 1300 [7] => 10 )

We also have many higher level PHP libraries that allow you to simplify the above code. The most popular are PEAR DB and ADOdb. Here are some of the differences between these libraries:

Feature PEAR DB 1.6 ADOdb 4.52

PEAR DB is good enough for simple web apps. But if you need more power, you can see ADOdb offers more sophisticated functionality. The rest of this article will concentrate on using ADOdb with Oracle. You can find out more about connecting to Oracle later in this guide.

ADOdb Example

In ADOdb, the above oci8 example querying the emp table could be written as:

include "/path/to/adodb.inc.php";
$db = NewADOConnection("oci8");
$db->Connect($tnsName, "scott", "tiger");

$rs = $db->Execute("select * from emp where empno>:emp order by empno",
array('emp' => 7900));
while ($arr = $rs->FetchRow()) {
print_r($arr);
echo "
";
}

The Execute( ) function returns a recordset object, and you can retrieve the rows returned using $recordset->FetchRow( ).

If we ignore the initial connection preamble, we can see the ADOdb version is much easier and simpler:

Oci8 ADOdb
$stmt = OCIParse($conn,
"select * from emp where empno > :emp");
$emp = 7900;
OCIBindByName($stmt, ':emp', $emp);
$ok = OCIExecute($stmt);

while (OCIFetchInto($stmt,$arr)) {
print_r($arr);
echo "
";
}
$recordset = $db->Execute("select * from emp where empno>:emp",
array('emp' => 7900));

while ($arr = $recordset->FetchRow()) {
print_r($arr);
echo "
";
}

2. ADOdb Query Semantics

You can also query the database using the standard Microsoft ADO MoveNext( ) metaphor. The data array for the current row is stored in the fields property of the recordset object, $rs. MoveNext( ) offers the highest performance among all the techniques for iterating through a recordset:

$rs = $db->Execute("select * from emp where empno>:emp", array('emp' => 7900));
while (!$rs->EOF) {
print_r($rs->fields);
$rs->MoveNext();
}

And if you are interested in having the data returned in a 2-dimensional array, you can use:

$arr = $db->GetArray("select * from emp where empno>:emp", array('emp' => 7900));

Now to obtain only the first row as an array:

$arr = $db->GetRow("select * from emp where empno=:emp", array('emp' => 7900));

Or to retrieve only the first field of the first row:

$arr = $db->GetOne("select ename from emp where empno=:emp", array('emp' => 7900));

For easy pagination support, we provide the SelectLimit function. The following will perform a select query, limiting it to 100 rows, starting from row 201 (row 1 being the 1st row):

$offset = 200; $limitrows = 100;
$rs = $db->SelectLimit('select * from table', $limitrows, $offset);

The $offset parameter is optional.

Array Fetch Mode

When data is being returned in an array, you can choose the type of array the data is returned in.

  1. Numeric indexes - use $connection->SetFetchMode(ADODB_FETCH_NUM).
  2. Associative indexes - the keys of the array are the names of the fields (in upper-case). Use $connection->SetFetchMode(ADODB_FETCH_ASSOC).
  3. Both numeric and associative indexes - use $connection->SetFetchMode(ADODB_FETCH_BOTH).

The default is ADODB_FETCH_BOTH for Oracle.

Caching

You can define a database cache directory using $ADODB_CACHE_DIR, and cache the results of frequently used queries that rarely change. This is particularly useful for SQL with complex where clauses and group-by’s and order-by’s. It is also good for relieving heavily-loaded database servers.

This example will cache the following select statement for 3600 seconds (1 hour):

$ADODB_CACHE_DIR = '/var/adodb/tmp';
$rs = $db->CacheExecute(3600, "select names from allcountries order by 1");

There are analogous CacheGetArray( ), CacheGetRow( ), CacheGetOne( ) and CacheSelectLimit( ) functions. The first parameter is the number of seconds to cache. You can also pass a bind array as a 3rd parameter (not shown above).There is an alternative syntax for the caching functions. The first parameter is omitted, and you set the cacheSecs property of the connection object:

$ADODB_CACHE_DIR = '/var/adodb/tmp';
$connection->cacheSecs = 3600;
$rs = $connection->CacheExecute($sql, array('id' => 1));

3. Using Prepare( ) For Frequently Used Statements

Prepare( ) is for compiling frequently used SQL statement for reuse. For example, suppose we have a large array which needs to be inserted into an Oracle database. The following will result in a massive speedup in query execution (at least 20-40%), as the SQL statement only needs to be compiled once:

$stmt = $db->Prepare('insert into table (field1, field2) values (:f1, :f2)');
foreach ($arrayToInsert as $key => $value) {
$db->Execute($stmt, array('f1' => $key, 'f2' => $val);
}

4. Working With LOBs

Oracle treats data which is more than 4000 bytes in length specially. These are called Large Objects, or LOBs for short. Binary LOBs are BLOBs, and character LOBs are CLOBs. In most Oracle libraries, you need to do a lot of work to process LOBs, probably because Oracle designed it to work in systems with little memory. ADOdb tries to make things easy by assuming the LOB can fit into main memory.

ADOdb will transparently handle LOBs in select statements. The LOBs are automatically converted to PHP variables without any special coding.

For updating records with LOBs, the functions UpdateBlob( ) and UpdateClob( ) are provided. Here’s a BLOB example. The parameters should be self-explanatory:

$ok = $db->Execute("insert into aTable (id, name, ablob)
values (aSequence.nextVal, 'Name', null)");
if (!$ok) return LogError($db->ErrorMsg());
# params: $tableName, $blobFieldName, $blobValue, $whereClause
$db->UpdateBlob('aTable', 'ablob', $blobValue, 'id=aSequence.currVal');

and the analogous CLOB example:

$ok = $db->Execute("insert into aTable (id, name, aclob)
values (aSequence.nextVal, 'Name', null)");
if (!$ok) return LogError($db->ErrorMsg());
$db->UpdateClob('aTable', 'aclob', $clobValue, 'id=aSequence.currVal');

Note that LogError( ) is a user-defined function, and not part of ADOdb.

Inserting LOBs is more complicated. Since ADOdb 4.55, we allow you to do this (assuming that the photo field is a BLOB, and we want to store $blob_data into this field, and the primary key is the id field):

$sql = "INSERT INTO photos ( ID, photo) ".
"VALUES ( :id, empty_blob() )".
" RETURNING photo INTO :xx"
;

$stmt = $db->PrepareSP($sql);
$db->InParameter($stmt, $id, 'id');
$blob = $db->InParameter($stmt, $blob_data, 'xx',-1, OCI_B_BLOB);
$db->StartTrans();
$ok = $db->Execute($stmt);
$db->CompleteTrans();

5. REF CURSORs

Oracle recordsets can be passed around as variables called REF Cursors. For example, in PL/SQL, we could define a function open_tab that returns a REF CURSOR in the first parameter:

TYPE TabType IS REF CURSOR RETURN TAB%ROWTYPE;

PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames IN VARCHAR) IS
BEGIN
OPEN tabcursor FOR SELECT * FROM TAB WHERE tname LIKE tablenames;
END open_tab;

In ADOdb, we could access this REF Cursor using the ExecuteCursor() function. The following will find all table names that begin with ‘A’ in the current schema:

$rs = $db->ExecuteCursor("BEGIN open_tab(:refc,'A%'); END;",'refc');
while ($arr = $rs->FetchRow()) print_r($arr);

The first parameter is the PL/SQL statement, and the second parameter is the name of the REF Cursor.

6. In and Out Parameters

The following PL/SQL stored procedure requires an input variable, and returns a result into an output variable:

PROCEDURE data_out(input IN VARCHAR, output OUT VARCHAR) IS
BEGIN
output := 'I love '||input;
END;

The following ADOdb code allows you to call the stored procedure:

$stmt = $db->PrepareSP("BEGIN adodb.data_out(:a1, :a2); END;");
$input = 'Sophia Loren';
$db->InParameter($stmt,$input,'a1');
$db->OutParameter($stmt,$output,'a2');
$ok = $db->Execute($stmt);
if ($ok) echo ($output == 'I love Sophia Loren') ? 'OK' : 'Failed';

PrepareSP( ) is a special function that knows about bind parameters. The main limitation currently is that IN OUT parameters do not work.

Bind Parameters and REF CURSORs

We could also rewrite the REF CURSOR example to use InParameter (requires ADOdb 4.53 or later):

$stmt = $db->PrepareSP("BEGIN adodb.open_tab(:refc,:tabname); END;");
$input = 'A%';
$db->InParameter($stmt,$input,'tabname');
$rs = $db->ExecuteCursor($stmt,'refc');
while ($arr = $rs->FetchRow()) print_r($arr);

Bind Parameters and LOBs

You can also operate on LOBs. In this example, we have IN and OUT parameters using CLOBs.

$text = 'test test test';
$sql = "declare rs clob; begin :rs := lobinout(:sa0); end;";
$stmt = $conn -> PrepareSP($sql);
$conn -> InParameter($stmt,$text,'sa0', -1, OCI_B_CLOB); # -1 means variable length
$rs = '';
$conn -> OutParameter($stmt,$rs,'rs', -1, OCI_B_CLOB);
$conn -> Execute($stmt);
echo "return = ".$rs."
";

Similarly, you can use the constant OCI_B_BLOB to indicate that you are using BLOBs.

Reusing Bind Parameters with CURSOR_SHARING=FORCE

Many web programmers do not care to use bind parameters, and prefer to enter the SQL directly. So instead of:

$arr = $db->GetArray("select * from emp where empno>:emp", array('emp' => 7900));

They prefer entering the values inside the SQL:

$arr = $db->GetArray("select * from emp where empno>7900");

This reduces Oracle performance because Oracle will reuse compiled SQL which is identical to previously compiled SQL. The above example with the values inside the SQL is unlikely to be reused. As an optimization, from Oracle 8.1 onwards, you can set the following session parameter after you login:

ALTER SESSION SET CURSOR_SHARING=FORCE

This will force Oracle to convert all such variables (eg. the 7900 value) into constant bind parameters, improving SQL reuse.

More speedup tips.

7. Dates and Datetime in ADOdb

There are two things you need to know about dates in ADOdb.

First, to ensure cross-database compability, ADOdb assumes that dates are returned in ISO format (YYYY-MM-DD H24:MI:SS).

Secondly, since Oracle treats dates and datetime as the same data type, we decided not to display the time in the default date format. So on login, ADOdb will set the NLS_DATE_FORMAT to ‘YYYY-MM-DD’. If you prefer to show the date and time by default, do this:

$db = NewADOConnection('oci8');
$db->NLS_DATE_FORMAT = 'RRRR-MM-DD HH24:MI:SS';
$db->Connect($tns, $user, $pwd);

Or execute:

$sql = "ALTER SESSION SET NLS_DATE_FORMAT = 'RRRR-MM-DD HH24:MI:SS'";
$db->Execute($sql);

If you are not concerned about date portability and do not use ADOdb’s portability layer, you can use your preferred date format instead.

8. Database Portability Layer

ADOdb provides the following functions for portably generating SQL functions as strings to be merged into your SQL statements:

Function Description
DBDate($date) Pass in a UNIX timestamp or ISO date and it will convert it to a date string formatted for INSERT/UPDATE
DBTimeStamp($date) Pass in a UNIX timestamp or ISO date and it will convert it to a timestamp string formatted for INSERT/UPDATE
SQLDate($date, $fmt) Portably generate a date formatted using $fmt mask, for use in SELECT statements.
OffsetDate($date, $ndays) Portably generate a $date offset by $ndays.
Concat($s1, $s2, …) Portably concatenate strings. Alternatively, for mssql use mssqlpo driver, which allows || operator.
IfNull($fld, $replaceNull) Returns a string that is the equivalent of MySQL IFNULL or Oracle NVL.
Param($name) Generates bind placeholders, using ? or named conventions as appropriate.
$db->sysDate Property that holds the SQL function that returns today’s date
$db->sysTimeStamp Property that holds the SQL function that returns the current timestamp (date+time).
$db->concat_operator Property that holds the concatenation operator
$db->length Property that holds the name of the SQL strlen function.
$db->upperCase Property that holds the name of the SQL strtoupper function.
$db->random Property that holds the SQL to generate a random number between 0.00 and 1.00.
$db->substr Property that holds the name of the SQL substring function.

ADOdb also provides multiple oracle oci8 drivers for different scenarios:

Driver Name Description
oci805 Specifically for Oracle 8.0.5. This driver has a slower SelectLimit( ).
oci8 The default high performance driver. The keys of associative arrays returned in a recordset are upper-case.
oci8po The portable Oracle driver. Slightly slower than oci8. This driver uses ? instead of :bindvar for binding variables, which is the standard for other databases. Also the keys of associative arrays are in lower-case like other databases.

Here’s an example of calling the oci8po driver. Note that the bind variables use question-mark:

$db = NewADOConnection('oci8po');
$db->Connect($tns, $user, $pwd);
$db->Execute("insert into atable (f1, f2) values (?,?)", array(12, 'abc'));

9. Connecting to Oracle

Before you can use ADOdb, you need to have the Oracle client installed and setup the oci8 extension. This extension comes pre-compiled for Windows (but you still need to enable it in the php.ini file). For information on compiling the oci8 extension for PHP and Apache on Unix, there is an excellent guide at oracle.com.

Should You Use Persistent Connections

One question that is frequently asked is should you use persistent connections to Oracle. Persistent connections allow PHP to recycle existing connections, reusing them after the previous web pages have completed. Non-persistent connections close automatically after the web page has completed. Persistent connections are faster because the cost of reconnecting is expensive, but there is additional resource overhead. As an alternative, Oracle allows you to pool and reuse server processes; this is called Shared Server (also known as MTS).

The author’s benchmarks suggest that using non-persistent connections and the Shared Server configuration offer the best performance. If Shared Server is not an option, only then consider using persistent connections.

Connection Examples

Just in case you are having problems connecting to Oracle, here are some examples:

a. PHP and Oracle reside on the same machine, use default SID, with non-persistent connections:

$conn = NewADOConnection('oci8');
$conn->Connect(false, 'scott', 'tiger');

b. TNS Name defined in tnsnames.ora (or ONAMES or HOSTNAMES), eg. ‘myTNS’, using persistent connections:

$conn = NewADOConnection('oci8');
$conn->PConnect(false, 'scott', 'tiger', 'myTNS');

or

$conn->PConnect('myTNS', 'scott', 'tiger');

c. Host Address and SID

$conn->connectSID = true;
$conn->Connect('192.168.0.1', 'scott', 'tiger', 'SID');

d. Host Address and Service Name

$conn->Connect('192.168.0.1', 'scott', 'tiger', 'servicename');

e. Oracle connection string:

$cstr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=$host)(PORT=$port))
(CONNECT_DATA=(SID=$sid)))";
$conn->Connect($cstr, 'scott', 'tiger');

f. ADOdb data source names (dsn):

$dsn = 'oci8://user:pwd@tnsname/?persist';  # persist is optional
$conn = ADONewConnection($dsn); # no need for Connect/PConnect

$dsn = 'oci8://user:pwd@host/sid';
$conn = ADONewConnection($dsn);

$dsn = 'oci8://user:pwd@/'; # oracle on local machine
$conn = ADONewConnection($dsn);

With ADOdb data source names, you don’t have to call Connect( ) or PConnect( ).

10. Error Checking

The examples in this article are easy to read but a bit simplistic because we ignore error-handling. Execute( ) and Connect( ) will return false on error. So a more realistic way to call Connect( ) and Execute( ) is:

function InvokeErrorHandler()
{
global $db; ## assume global
MyLogFunction($db->ErrorNo(), $db->ErrorMsg());
}
if (!$db->Connect($tns, $usr, $pwd)) InvokeErrorHandler();

$rs = $db->Execute("select * from emp where empno>:emp order by empno",
array('emp' => 7900));
if (!$rs) return InvokeErrorHandler();
while ($arr = $rs->FetchRow()) {
print_r($arr);
echo "
";
}

You can retrieve the error message and error number of the last SQL statement executed from ErrorMsg( ) and ErrorNo( ). You can also define a custom error handler function. ADOdb also supports throwing exceptions in PHP5.

Handling Large Recordsets (added 27 May 2005)

The oci8 driver does not support counting the number of records returned in a SELECT statement, so the function RecordCount() is emulated when the global variable $ADODB_COUNTRECS is set to true, which is the default. We emulate this by buffering all the records. This can take up large amounts of memory for big recordsets. Set $ADODB_COUNTRECS to false for the best performance.This variable is checked every time a query is executed, so you can selectively choose which recordsets to count.

11. Other ADOdb Features

Schema generation. This allows you to define a schema using XML and import it into different RDBMS systems portably.

Performance monitoring and tracing. Highlights of performance monitoring include identification of poor and suspicious SQL, with explain plan support, and identifying which web pages the SQL ran on.

12. Download

You can download ADOdb from sourceforge. ADOdb uses a BSD style license. That means that it is free for commercial use, and redistribution without source code is allowed.

13. Resources