Blog

  • Testing MathJax

    Writing maths works as in LaTeX. Use dollar signs to enclose inline math, e.g. \(x^2\) \(x^2\) \(x^2\) $$x^2$$

    \(
    \begin{align}
    E &= mc^2 \\
    m &= \frac{m_0}{\sqrt{1-\frac{v^2}{c^2}}}
    \end{align}
    \)

    \(\int_{-\infty}^\infty e^{-\pi x^2}\,\mathrm{d}x=1\label{a}\tag{1}\)

    \ref{a}
  • This is a reasonably complete sample of using MathJax.

    Sample has been taken form here:
    https://groups.drupal.org/node/1263

    MathJax documentation is here:
    http://docs.mathjax.org/en/latest/

    Wonder how much of this works:
    https://yutsumura.com/mathjax-in-wordpress/

    Writing maths works as in LaTeX. Use dollar signs to enclose inline math, e.g. \(x^2\).

    Examples for paragraph math are \(x^2 \) and \(x^2\) (both variants are equivalent).

    There is also a display-style inline math environment, compare \(\sum_{k=1}^\infty \frac{1}{k}\) and \(!\sum_{k=1}^\infty \frac{1}{k}\).

    To make a dollar sign, you have to type \$ as in LaTeX!
    Using just $ doesn’t work.
    Latex: \(\$ \)
    and
    Latex: \($ \)

    Arbitrary LaTeX code can be rendered as in this example:
    Let $x^2$ be a natural number. 

    There are also more elaborate environments to write math – they support auto-numbering, referencing and more. These environments are <equation> and <equations>. They both support the same attributes.

    E.g. rendering an equation with a different resolution:
    <equation>e^{i \cdot \pi} = -1<equation>.

    To give the equation automatically a number, you have to give it an id:
    e^{i \cdot \pi} = -1.

    You now can produce a link to that equation by typing \\ref{euler}, or even better (\\ref{euler}).

    You can also give it a name instead of a number:
    e^{i \cdot \pi} = -1.

    An example for the <equations> environment is given by:
    \(
    \int \ln(x) \;dx
    &= \int 1 \cdot \ln(x) \;dx \
    &= x \cdot \ln(x) – \int x \cdot \frac{1}{x} \;dx \
    &= x \cdot \ln(x) – x
    \)

    The spaces on the left are optional.

    To prohibit some text from being processed by DruTeX, you can use <code> and <notex>:
    e.g. $x^2$
    or
    $x^2$
    Humm… doesn\’t work!

    \(\left(\int_{-\infty}^\infty e^{-x^2}\ dx\right)^2\ =\ \pi (\ref{test}) \)

    Extra bit

    \(e^{ \pm i\theta } = \cos \theta \pm i\sin \theta\)

  • Using drush with drupal

    Using drush has been remarkably simple.

    I downloaded it as instructed on their site, and it almost works straight away. It was annoying to keep having to tell drush the site to use with the -l flag though, so I have configured it for my needs.

    I did this by making a .drush directory, and copying the example aliases.drush.php and drushrc.php in. I then amended drushrc.php to refer to my site and install directory.

    Having done that I have then began to use it.

    I think being able to update the core using:

     drush up drupal 

    to be very cool!

    Similarly I can check the module status using:

     drush ups 

    Individual modules can be done using:

     drush up <module>

    And then I can download modules using (make sure you are in the right place!):

     drush dl <module>

    And then enable and disable modules using:

     drush <en|dis> <module> 

    In short, I really like drush!

  • Getting annoying error with phpMyAdmin

    I upgraded phpMyAdmin from 4.1.2 from 4.2.6. Having done this, I copied in the config.inc.php file and started everything up.

    Logged in and I get “You should upgrade to MySQL 5.5.0 or later.”.

    Well yes, I should. But I can’t (the mysql version is attached to the NAS – so i can’t really change that very easily). But I want to use phpMyAdmin. Checked on phpMyAdmin site, and it says “supported only on MySQL 5.5”.

    Anything after here is at your own risk. I have not comprehensively tested this, nor have I any intention of doing that.

    Right, so with that out of the way, After digging about for a little bit I found that the error is being generated by:

    libraries/common.inc.php

    If you open this up, there is a line:

            if (PMA_MYSQL_INT_VERSION < 50500) {

    Change it to say:

            if (PMA_MYSQL_INT_VERSION < 50100) {

    And now “hey presto!” it won’t complain anymore.

    Although we SHOULD all really upgrade to MySQL 5.5, or MariaDB, or move to PostgreSQL

    Again, if you do this and it breaks things its not my fault.
    I wanted to make it so i could see tables in MySQL again. I rarely user phpMyAdmin for much more than that anyway.

  • Configuring GIT

    First up, I found most of my information on this here:

    Seth Robertson – Git On The Web

    The one thing that I didn’t realise initially is that you can’t use the gitweb URL to do clones etc.
    I spent ages trying to do this, until I found Seth’s page. It explains things in a very structured manner that can be applied to most situations I suspect.

    The only other thing I think I should point out is related to rewrites. If you are using them in an Apache configuration section that is higher than site that everything will be accessed from you need to remember to set the following, otherwise they will be ignored:

            RewriteEngine On
            RewriteOptions Inherit

    So, in my case, I am accessing git via a VirtualHost that I have. The virtual host needed these lines adding to it otherwise the rewrite configuration in conf.d/gitweb didn’t get picked up.

    To enable LDAP, I also had to do this:

            sudo a2enmod authnz_ldap
            sudo a2enmod cgi
            sudo service apache restart

    In the end, to have a Git Repository​ authenticating with LDAP (with Group) authenticating, with GitWeb, some aliases, source IP restrictions and some rewrites to a gitweb file that looks like this:

    Alias /<gitweb alias> /usr/share/gitweb
    Alias /<shortened gitweb alias> /usr/share/gitweb
    
    RewriteEngine On
    RewriteRule ^/<shortened gitweb alias>/([^/]+)$ /g/?p=$1 [R,NE]
    RewriteRule ^/<shortened gitweb alias>//([^/]+)/([0-9a-f]+)$ /<shortened gitweb alias>/?p=$1/.git;a=commitdiff;h=$2 [R,NE]
    RewriteRule ^/<shortened gitweb alias>/([^/]+)/([0-9a-f]+)$ /<shortened gitweb alias>/?p=$1;a=commitdiff;h=$2 [R,NE]
    
    <Directory /usr/share/gitweb>
      Options FollowSymLinks +ExecCGI
      AllowOverride all
      AddHandler cgi-script .cgi
      Order deny,allow
      Deny from all
      Allow from <restricting IP addresses>
      SSLRequireSSL
      AuthType basic
      AuthName "Private git repository"
      AuthBasicProvider ldap
      AuthLDAPURL "ldap://<ldap server>:<port>/<LDAP User DN>?<LDAP User ID>?sub?(objectClass=*)"
      Require valid-user
      AuthLDAPGroupAttribute memberUid
      AUthLDAPGroupAttributeIsDn off
      Require ldap-group <LDAP Group DN>
    </Directory>
    
    ScriptAlias /<shortened git alias>/ /usr/lib/git-core/git-http-backend/
    <Directory "/usr/lib/git-core/">
      Options +ExecCGI
      SetEnv GIT_PROJECT_ROOT <path to projects>
      SetEnv GIT_HTTP_EXPORT_ALL
      Order deny,allow
      Deny from all
      Allow from <restricting IP addresses>
      SSLRequireSSL
      AuthType basic
      AuthName "Private git repository"
      AuthBasicProvider ldap
      AuthLDAPURL "ldap://<ldap server>:<port>/<LDAP User DN>?<LDAP User ID>?sub?(objectClass=*)"
      Require valid-user
      AuthLDAPGroupAttribute memberUid
      AUthLDAPGroupAttributeIsDn off
      Require ldap-group <LDAP Group DN>​
    </Directory>

    And we are done (well other than making the virtual host allow the rewrites).

    Just to prove it, here is a sample checkout:

    ~/temp$ git clone https://<server>/<GIT Alias>/test.git
    Cloning into 'test'...
    Username for 'https://<server>': <good user>
    Password for 'https://<good user>@<server>': 
    remote: Counting objects: 10, done.
    remote: Compressing objects: 100% (6/6), done.
    remote: Total 10 (delta 0), reused 4 (delta 0)
    Unpacking objects: 100% (10/10), done.
    ~/temp$ rm -rf test
    ~/temp$ git clone https://<server>/<GIT Alias>/test.git
    Cloning into 'test'...
    Username for 'https://<server>': <bad user>
    Password for 'https://<bad user>@<server>': 
    fatal: Authentication failed
  • Updating Language of postings in Drupal.

    Everything said it was undefined language (very weird).

    Found this post so I ran this update:

    UPDATE node SET language = 'en' WHERE language = 'und';

    And it did exactly what it says on the tin (turned everything set to und to en).

    Perfect!

  • Linking Drupal to QNAP LDAP

    This was way more simple than I expected.

    For reference, I have a separate server running my Drupal Installation. The QNAP sits along side it (but not accessible to the web). 

    I basically just added the LDAP module to the Drupal installation. I also had to install the Entity module for LDAP to use. Then I enabled LDAP functionality bit by bit, testing as I went. The first module was LDAP Servers. 

    Enabling this resulted in a request to install the PHP LDAP module on the server. Once that was in place, the module would enable. I then set up links back to my LDAP server. The only additional thing I needed on the LDAP server, was a service account for Drupal to bind with (which I created).

    Setting up the user relationship was easy:
    I set the base DN to my domain name.
    Then I set AuthName to be UID AccountName is also set to be UID
    The Email attribute is mail
    I then set the “Expression for the user DN” to “uid=%username,ou=people,%basedn”

    Setting up the group configuration proved the biggest stumbling point. The important bit to get right it that it asks for the Group Object Class, and not the name thing that holds the group. I miss understood the question here initially, especially as my container is called group, and that was one of the examples. What I needed to put in here was posixGroup.

    Then I told it only that LDAP Group Entry Attribute was memberuid and the this field actually held the UID.

    Once this was done, I could turn it on and test it.

    Now I enabled the LDAP User and LDAP Authentication modules.

    In the LDAP User module, I just told it to associate accounts together if an LDAP one existed (second option).
    I didn’t want two way provisioning, so I have left that unset.

    In the Authentication module, I initially left it mixed mode until I was confident it worked, at which point I have moved it to the second authentication option. The rest of this section I have left default. 

    It was after setting this up that I did my first proper test of everything using another browser to prevent cookie clashes etc.

    Once i was 100% sure that I could login as administrator still, and also login as my proper user. Once I was happy with this, THEN I altered authentication to the second mode. 

    Now I moved on to LDAP Authorization. I enabled this module went to configure it, and found that without a module to use it with it didn’t do much. 

    So I enabled the LDAP Authorization – Drupal Roles module too. The setup of this module was also very simple. I simply told it to use my LDAP server, and then explained how to map my LDAP groups to the Drupal groups.

    The only real fly in the ointment was that I was initially not looking to the groups correctly, as I thought that it was looking for the container of the groups, and not the Object Class of the group.

    Once I resolved that all the test worked properly and I have a working system that automatically adds people to drupal if they exist in the LDAP, and also correctly sets up their groups for them.

    Very pleased.

  • Time zones, Oracle Agents, Java, and the paths to madness…..

    I was attempting to re-install the Grid Control agents on two RHEL 6 servers today today. They’d had been upgraded from RHEL 5 to 6 and I wanted to see what needed to be done to re-attach them to Grid Control if we didn’t take the existing installation. I was having some issues with it (the agent wouldn’t start up – complained about “OMS decided to shutdown the agent because of the following reason sent from OMS: AGENT_TZ_MISMATCH”) After a bit of digging I started to find various levels of weirdness occurring. 

    I started off looking in Grid Control.

    If you look at the hosts table of grid control:

    select Timezone_region, count(*) from sysman.mgmt_targets group by Timezone_region order by 2;

    You see we have a nice interesting selection of TimeZones in use:

    +00:00				2
    Europe/Isle_of_Man		6
    +01:00				8
    Europe/Guernsey			26
    Europe/Lonon			49
    Europe/Jersey			59
    GB				80
    Europe/Belfast			85
    GB-Eire				367 

    That’s a wee bit scary – why on earth do all the servers think they are scattered over most of England (including the Channel Islands). We are based in London. Now I have checked a bit and at the OS level we set the timezone using:

    /etc/sysconfig/clock

    To:

    ZONE="Europe/London"

    And date is always sensible too:

    Wed Feb 20 15:39:01 GMT 2013

    So there I think there is some weirdness at work when the agent tries to work out the time zone in use. You can see what the agent thinks the zone is using:

    cd [agent home]/bin
    ./emctl config agent getTZ

    Depending on the server you run it on you get different answers:

    Europe/Guernsey
    GB
    GB-Eire
    GB

    Ignore the apparent consistency here, it isn’t true…. I found a chunk of Java code in a Oracle Support note (330737.1) that seemed show the same results (I expanded it slightly to check another set of values):

    import java.util.*;
    public class TestTZ
    {
      public static void main(String[] args)
      {
         System.out.println("Local Timezone:    "+(TimeZone.getDefault()).getDisplayName());
         System.out.println("Local ID:          "+(TimeZone.getDefault()).getID());
         TimeZone tz = Calendar.getInstance().getTimeZone();
         System.out.println("Calendar TimeZone: "+tz.getDisplayName());
         System.out.println("Calendar ID:       "+tz.getID());
      }
     }

    The output looks the same as what the agent reports. But I couldn’t find a pattern to what was goin on. In desperation I moved to looking at the actual timezone files … Its safest note to ask why.. lets just say I was desperate and looking for any possible reason for this now.  I used the md5sum of localtime:

    $ md5sum /etc/localtime 410c65079e6d14f4eedf50c19bd073f8  /etc/localtime  

    And then found zone files that had the same md5sum (just don’t ask why I started to do this):

    $ find /usr/share/zoneinfo -type f | xargs md5sum | grep 410c65079e6d14f4eedf50c19bd073f8
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Guernsey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB-Eire
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Guernsey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB-Eire

    Its worth pointing out here that they are actually all just links to the same file (the file system inodes match).  Now when I looked at these I (finally) started to see some consistency. The file at the top of this list matches the zone reported back. So on the first server I see:

    -bash-4.1$ find /usr/share/zoneinfo -type f | xargs md5sum | grep 410c65079e6d14f4eedf50c19bd073f8
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Guernsey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB-Eire
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB-Eire
    -bash-4.1$ ./emctl config agent getTZ
    Oracle Enterprise Manager 12c Cloud Control 12.1.0.1.0 
    Copyright (c) 1996, 2012 Oracle Corporation. 
    All rights reserved.
    Europe/Guernsey  

    On a second server, I see:

    -bash-4.1$ find /usr/share/zoneinfo -type f | xargs md5sum | grep 410c65079e6d14f4eedf50c19bd073f8
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Guernsey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Guernsey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB-Eire
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB-Eire
    -bash-4.1$ ./emctl config agent getTZ
    Oracle Enterprise Manager 12c Cloud Control 12.1.0.1.0 
    Copyright (c) 1996, 2012 Oracle Corporation. 
    All rights reserved.
    GB  

    For the OS, much like a database, the order that files are returned here is indeterminant. To make it determinant, and order would have to be imposed. It hasn’t been, and it looks like the method being used by the agent (and Java) to determine the timezone is equally unordered. An OS colleague and I then tried an experiment. He removed the top file (Europe/Guernsey) from the first system:

    -bash-4.1$ find /usr/share/zoneinfo -type f | xargs md5sum | grep 410c65079e6d14f4eedf50c19bd073f8
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/posix/GB-Eire
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/London
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Isle_of_Man
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Jersey
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Belfast
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB
    410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/GB-Eire

    Once he did this, the zone reported shifted to the next line:

    -bash-4.1$ ./emctl config agent getTZ
    Oracle Enterprise Manager 12c Cloud Control 12.1.0.1.0 
    Copyright (c) 1996, 2012 Oracle Corporation. 
    All rights reserved.
    Europe/London
    -bash-4.1$ java TestTZ
    Local Timezone:    		Greenwich Mean Time
    Local ID:          			Europe/London
    Calendar TimeZone: 	Greenwich Mean Time
    Calendar ID:       		Europe/London  

    So what does all of this tell me (and therefore you)? We have a bit of a problem (especially with java). If (for whatever the reason) code wants to look up what the timezone is, it just gets the top row of the unsorted list. Which is ridiculously stupid. The way to avoid this it to impose our own Timezone. If we set the TZ environment value:

    export TZ=Europe/Belfast  

    It will then be picked up by java in preference:

    -bash-4.1$ java -cp ~ TestTZ
    Local Timezone:    Greenwich Mean Time
    Local ID:          Europe/Belfast Calendar
    TimeZone: Greenwich Mean Time
    Calendar ID:       Europe/Belfast
    -bash-4.1$ ./emctl config agent getTZ
    Oracle Enterprise Manager 12c Cloud Control 12.1.0.1.0 
    Copyright (c) 1996, 2012 Oracle Corporation. 
    All rights reserved.
    Europe/Belfast

    So we can impose consistency again (although don’t use Belfast, that was to prove a point). This means two things: Going forward, we will have to add the setting of the TZ environment variable at the server level. This value will be Europe/London (so its consistent with /etc/sysconfig/clock). This means things running on new servers will know they are in Europe/London and going forward things will be fine. We also need to set the TZ value in .profile and .bash_profile for any Oracle Agent user especially where Java is being used (so WebLogic). This will then bring consistency back to the agents (and any other java installs). That said, for agents you will need to have the following run on them as they are fixed:

    ./emctl stop agent
    ./emctl resetTZ agent

    This sets the values in the properties file correctly. After that has happens the agent setup also needs changing in the database:

    alter session set current_schema=[oms user];
    exec mgmt_target.set_agent_tzrgn('[oms server]:[port]','Europe/London');
    commit;

    And then the agent can be started:

    ./emctl start agent

    All of this will make agents consistent in the system again, and should prevent weird answers about timezones from java going forward (which hopefully should prevent java date/time zone weirdness in the future).  Its important to note this is a general Java issue – any java app could show similar symptoms. Now if anyone wants me I’ll be in a darkened room bashing my head against a wall and mumbling about Oracle and my hatred of Java.

  • Using Oracle InstantClient 11g with PHP onto RHEL 5 with SELinux

    This is an example of using the Oracle InstantClient 11g with PHP.

    Installation InstantClient for PHP

    This is based on work from the past – but I appeared to have done the following:

    1. Installed InstantClient and Pear to manage the php installation.
      • sudo yum install php-pear
      • sudo rpm -ivh oracle-instantclient11.1-basic-11.1.0.7.0-1.i386.rpm
      • sudo rpm -Uvh oracle-instantclient11.1-devel-11.1.0.7.0-1.i386.rpm
    2. Update the library cache to include oracle:
      • sudo vi /etc/ld.so.conf.d/oracle.conf 
      • This file just contains the line: 
        /usr/lib/oracle/11.1/client/lib
    3. Used pecl to install the OCI client into PHP:
      • sudo pecl install oci8
    4. Updated PHP to then make use of the installed module
      • sudo vi /etc/php.d/oci8.ini
      • This file just contained
        ; Enable oci8 extension module
        extension=oci8.so
    5. I then restarted the web server.
      • sudo /etc/init.d/httpd restart

    Testing

    You can then test this by creating a php file with the following content:

    <?php      
    $conn = oci_connect('[user]', '[password]', ' [//]host_name[:port][/service_name][:server_type][/instance_name]');       
    $query = 'select table_name from user_tables';       
    $stid = oci_parse($conn, $query);       
    oci_execute($stid, OCI_DEFAULT);       
    while ($row = oci_fetch_array($stid, OCI_ASSOC)) {       
      foreach ($row as $item) {       
        echo $item." ";       
      }       
      echo "&lt;br&gt;\n";       
    }       
    oci_free_statement($stid);       
    oci_close($conn);       
    ?>

    Then use a browser to get to this web page, and it should show you the content of user_tables.

    Troubleshooting

    Then, if SELinux its not turned off then the following is needed, (but we don’t want to do it this way as it’s painful and make SELinux a bit pointless):

    sudo chcon -t textrel_shlib_t '/usr/lib/oracle/11.1/client/lib/libnnz11.so'       
    sudo chcon -t textrel_shlib_t '/usr/lib/oracle/11.1/client/lib/libclntsh.so.11.1'       
    sudo chcon -t textrel_shlib_t '/usr/lib/php/modules/oci8.so'       
    sudo execstack -c /usr/lib/oracle/11.1/client/lib/libclntsh.so       
    sudo execstack -c /usr/lib/oracle/11.1/client/lib/libclntsh.so.11.1       
    sudo execstack -c /usr/lib/oracle/11.1/client/lib/libnnz11.so       
    sudo chcon -u system_u '/usr/lib/php/modules/oci8.so'       
    sudo execstack -s /usr/sbin/httpd       
    sudo /usr/sbin/setsebool -P httpd_can_network_connect 1
  • Oracle eBusiness Submit Job – PL/SQL

    Again, a simple piece of code:

    This also runs Active User concurrent program:

    declare
      v_request_id number := -1;
    begin
      --fnd_global.apps_initialize(user_id, resp_id, appl_resp_id)
      fnd_global.apps_initialize(0, 20420, 1); --So sysadmin using responsibility System Administrator in application System Administration
      --v_request_id : fnd_request.submit_request(application short name,concurrent program short name,argument1 =>,  argument2 =>))
      v_request_id := fnd_request.submit_request(application=>'FND',program=>'FNDSCURS');
      commit;
      if v_request_id > 0
      then
        dbms_output.put_line('Successfully submitted: '||v_request_id);
      else
        dbms_output.put_line('Not Submitted');
      end if;
    end;
    /

    You can work out the application ids etc using these pieces of SQL:

    select * from fnd_application_tl
    where application_id = 1;
    select * from fnd_user
    where user_name = 'SYSADMIN';
    select * from fnd_responsibility_tl
    where responsibility_name = 'System Administrator';

    Easiest place to check the program short name etc is in eBusiness Suite itself.

    Once you get this working, you can increase the complexity. For example I took the above code and added calls to get users id:

    declare
      procedure fSubmitJob ( vSourceName varchar2, vTargetName varchar2)
      is
        v_request_id number := -1;
        v_source_id  number :=null;
        v_target_id  number :=null;
      begin
        select user_id
        into  v_source_id 
        from fnd_user
        where user_name = vSourceName; 
        select user_id
        into  v_target_id
        from fnd_user
        where user_name = vTargetName; 
        if ( v_source_id is not null and v_target_id is not null )
        then
          v_request_id := fnd_request.submit_request(application=>'<our app>',program=>'<our prog>',argument1 => v_target_id,  argument2 =>v_source_id);
          commit;
          if v_request_id > 0
          then
            dbms_output.put_line('Successfully submitted'); -–Removed rest of message
          else
            dbms_output.put_line('Failed submit'); -–Removed rest of message
          end if;
        else
          dbms_output.put_line('Missing ID'); -–Removed rest of message
        end if;
      end fSubmitJob;
    begin
      fnd_global.apps_initialize(0, 20420, 1);
      fSubmitJob('<user>','<another user>');
      fSubmitJob('<user>','<another user>');
    end;
    /

    In this it was easier to code a function to find user ids and run a job each time, than do the equivalent code in shell script.