Handling positional and non-positional command line arguments from a shell script

When you want to use non-positional command line arguments together with positional you may use getopts to parse non-positional arguments and than use $OPTIND environment variable set by getopts to access positional arguments.

Of course positional arguments should follow non-positional ones. Let’s assume you plan to have following syntax:

script.sh [options] ARG1 ARG2

At first you have to parse non-positional arguments which will be options in this case with getopts:

while getopts "h:u:p:d:" flag; do
case "$flag" in
    h) HOSTNAME=$OPTARG;;
    u) USERNAME=$OPTARG;;
    p) PASSWORD=$OPTARG;;
    d) DATABASE=$OPTARG;;
esac
done

Than you may want to ensure that required positional arguments were passed:

if [ $(( $# - $OPTIND )) -lt 1 ]; then
    echo "Usage: `basename` [options] ARG1 ARG2"
    exit 1
fi

Later you can access positional arguments using array expansion ${@:START:1}:

ARG1=${@:$OPTIND:1}
ARG2=${@:$OPTIND+1:1}

How to get the full path from the running bash script

If you need to get an absolute path of the script folder within the running shell script you may use readlink and dirname commands:

#!/bin/sh
echo $(dirname $(readlink -f $0))

PHP 5.3.0 open_basedir bug

If you experience open_basedir restrictions in PHP 5.3.0 while active open_basedir path should allow script execution this is a known PHP bug: Bug #48744 and Bug #48880.

Source of this issue lies in fopen_wrappers.c and is already fixed in svn.

Here is the patch you can safely apply to PHP 5.3.0 sources to fixing this issue:

--- php/php-src/branches/PHP_5_3/main/fopen_wrappers.c	2009/06/18 06:38:30	282359
+++ php/php-src/branches/PHP_5_3/main/fopen_wrappers.c	2009/07/31 21:09:45	286602
@@ -93,7 +93,7 @@
 
 	p = (char **) (base + (size_t) mh_arg1);
 
-	if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN) {
+	if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) {
 		/* We're in a PHP_INI_SYSTEM context, no restrictions */
 		*p = new_value;
 		return SUCCESS;

Setting up external authentication in Apache with pwauth

The best way to use PAM authentication in Apache looks to be external authentication with help of pwauth tool. Unfortunately this tool has quite tricky installation procedure. Here is a great article with detailed information about compiling, testing and installing pwauth under Ubuntu.

PHP 5.2.10 comes with a broken PEAR

If you have a problem with PEAR which comes with PHP 5.2.10 and receiving messages like “pear.php.net is using a unsupported protocal” most probably you have broken PEAR channel data files located at PREFIX/lib/php/.channels/. You need to replace them with files from working installation of PEAR.

Here is an archived .channels/ folder with working data files.

Update: Official solution is simpler – just remove .channels directory and run pear update-channels.

cd `pear config-get php_dir`
rm -r .channels
pear update-channels

Running Apache 2.2 in a foreground

It took a while for me to find out how to leave Apache 2.2 running in a foreground, since old -F switch were not available. So, to leave apache in a foreground u need to run it with -D FOREGROUND command line parameter.

/user/bin/httpd -D FOREGROUND

migration of mysql 5.0 to new host

Recently when I decided to move db to new server no clear info found about how to do that.
Very simple.
Old server: FreeBSD 6.2-RELEASE amd64. Mysql: 5.0.51a FreeBSD port: mysql-server-5.0.51a
New server: FreeBSD 7.2-RELEASE i386 Mysql: 5.0.77 FreeBSD port: mysql-server-5.0.77_1

As far as I had a default directories and conf’s of mysql, copying of /var/db/mysql to new location did work. Both sides mysql servers should be stopped during transfer. Extra check of /var/db/mysql to be owned and chmoded to 700 to mysqld server’s user.
That was easier than I thought.

Enable XDebug in Zend Studio for Eclipse

Ever wanted to use XDebug for remote debugging in Zend Studio for Eclipse instead of standard Zend Debugger? Here is a good post about how to do this.

JavaScript recursive SetTimeout

A simple JavaScript solution for recursively setting timeout and running some operation periodically with maximum number of iterations support and only anonymous functions.

1
2
3
4
5
6
7
8
9
10
(function(){
    var t_count = 0;
    (function(delay, count) {
        setTimeout(function() {
            if (count && ++t_count > count) return;
            // do your stuff here
            setTimeout(arguments.callee, delay);
        }, delay);
    })(200, 10);
})();

If you will omit second argument to anonymous function than operation will run infinitely.

1
2
3
4
5
6
7
8
(function(){
    var t_count = 0;
    (function(delay, count) {
        setTimeout(function() {
        //...
        }, delay);
    })(200);
})();

Its even possible to constantly increase delay between operations.

1
2
3
4
5
6
7
8
(function(){
    var t_count = 0;
    (function(delay, count) {
        setTimeout(function() {
        //...
        }, delay * 0.5);
    })(200);
})();

Javascript function(){}() vs (function(){})()

What’s the difference between function(){}() and (function(){})() JavaScript constructions? Both are right away executed anonymous functions. I have asked this question to myself mainly because of context where I have used them and they seemed to be equal to me:

1
2
3
4
5
6
7
var f1 = function(){
    return 'value1';
}();
 
var f2 = (function(){
    return 'value2';
})();

I was assigning return value from function to a variable and it worked the same good for both versions with and without extra set of parentheses. After playing a bit and investigating jQuery code it become clear to me that the difference is in a standalone execution. Function with extra set parentheses you can be executed anonymously while variant without parentheses can only be used in a right side of assignment.

1
2
3
4
5
6
7
8
9
// does not work (syntax error)
function(){
    return 'value1';
}();
 
// works fine
(function(){
    return 'value1';
})();