Korn Shell Functions

July 20, 2008 by unbeta

Korn Shell functions are an easy way to break larger Korn Shell scripts into more manageable chunks. You have the option of using the function to return a true/false value as well as normal number or string output. The basic format of a function in the Korn Shell is like this:

function test_function {

typeset local_variables

body_of_function

}

It’s always a good idea to declare your local variables in a function using the ‘typeset’ command so they don’t inherit values from calling functions or scripts. The command-line parameters become localized in a function so ‘$1’ isn’t the same as the ‘$1’ that was passed to the originating script. If you want to pass parameters to a function, call it with the values like this: “test_function parameter1 parameter2”. If you want to pass on the original values passed to the script on the command line, pass them to the function like this: “test_function $1” or to pass all of the parameters, like this: “test_function $@”. Please note use of the ‘shift’ statement will clear out the command line switches so this will not work if the command line switches have been parsed and removed from the environment.

The returning of true/false values from functions is counter intuitive when you are more familiar with other languages. In Korn Shell, a value of zero passed back from a function equals ‘true’ and a value of non-zero equals ‘false’. So, here’s how this plays out:

function test_name {

typeset FIRST=”$1”

typeset LAST=”$2”

if [[ “$FIRST” = “$LAST” ]]

then

return 0

else

return 1

fi

}

read FIRST?”Enter first name: “

read LAST?”Enter last name: “

if test_name “$FIRST” “$LAST”

then

print “First name equals last”

else

print “First name does not equal last”

fi

Now, when this script is executed, it asks for a first and last name and indicates if they are the same. This is not very useful as a script but it illustrates the true/false return quite nicely. It should be noted that functions return the value of the last statement executed. The ‘return’ statement exits the function as well as providing the appropriate feedback. Also, note that double-quotes were used to supply the parameters to the function. This ensures that the entire variable is passed as “$1” or “$2” instead of interpreting spaces as a separator in the call.

Here’s an example of a function returning a string value instead of Boolean:

function full_name {

typeset FIRST=”$1”

typeset LAST=”$2”

print “$FIRST $LAST”

}

read FIRST?”Enter first name: “

read LAST?”Enter last name: “

print “Full Name=$(full_name “$FIRST” “$LAST”)”

This brings up another interesting point. You can call a function using the old-style of the grave symbols:

print “Full Name=`full_name “$FIRST” “$LAST”`”

Or, you can use the non-deprecated form presented in the previous example.

One other concern is how to successfully call Boolean functions in a ‘if’ call. Here’s a simple example:

if [[ test_name “henry” “henry” && “$ME” = “henry” ]]

then

print “hi henry”

fi

This won’t work! The Boolean and the non-boolean portions need to be separated. So, here’s the correct way to combine the two:

if test_name “henry” “henry” && [[“$ME” = “henry” ]]

then

print “hi henry”

fi

Hopefully this blog entry has encouraged the use of functions in shell scripting. Thanks.

Awk Tips

December 27, 2007 by unbeta

Return all fields to the right of a particular field:

echo “testing|1|2|3|4″ | awk -F \| ‘{for (i=3;i<NF+1;i++) o = (o FS $i)} END {print substr(o,2)}’

or

echo “testing|1|2|3|4″ | awk -F \| ‘{print substr($0, index($0,$3)) }’  (See original link)

results in: ‘2|3|4′ or starting with the third field, all fields to the right.

To format an integer with comma-separators:

echo “123456″ | awk ‘{for (i=1;i<length($0)+1;i++) if ((!(i%3)) && (i!=length($0))) o = (“,” substr($0,length($0)-i+1,1) o); else o = (substr($0,length($0)-i+1,1) o)} END {print o}’

results in ‘123,456′

Oracle RDBMS Tips

November 12, 2007 by unbeta

Two-phase commit views:

dba_2pc_neighbors

dba_2pc_pending

To kill all non-local database connections in UNIX:

ps -ef | grep LOCAL=NO | grep ${ORACLE_SID} | awk ‘{print $2}’ | while read pid; do kill -9 $pid; done

Windows Tips

November 12, 2007 by unbeta

Program for creating UNIX-like symbolic links in NTFS:

junction.exe from sysinternals.com

Oracle Application Server Tips

November 12, 2007 by unbeta

Location of config file that lists all ports set up during initial install of 10gAS:

$ORACLE_HOME/install/portlist.ini

SED Tips

November 12, 2007 by unbeta

To convert a string to proper-case:

sed ’s/\b\(\w*\)\b/\L\u\1/g’

Example: echo “this is a test of SED” | sed ’s/\b\(\w*\)\b/\L\u\1/g’

Output: This Is A Test Of Sed

Unix Tips

November 6, 2007 by unbeta

Example of how to make a crontab execute a script at the same time every two weeks:

01 2 * * 1 (( `/bin/date +\%W` \% 2 )) || /opt/my_script_name

In linux, executes ‘my_script_name’ at 02:01 am every other Monday.

Example of how to make a crontab execute a script every five minutes:

*/5 * * * * /opt/my_script_name

In linux, executes ‘my_script_name’ every five minutes.

Linux boot logs:

/var/log/boot.log

/var/log/dmesg

To kill user sessions holding a mount point:

fuser -kxuc {Directory}

To correct the problem with puTTY displaying single tick marks incorrectly:

cp /etc/sysconfig/i18n ~/.i18n

change the first line in ~/.i18n to: LANG=”en_US”

In linux, forcing a reload of the /etc/inittab:

kill -HUP 1

or

init q

In linux, the equivalent command for ‘whence’:

‘which’

Korn Shell CGI for Web Pages

November 6, 2007 by unbeta

Recently I came across something I consider incredibly cool and I thought I would share here. I’ve always wanted to write simple web pages in Korn Shell, the language I’m currently using extensively and therefore most familiar with. Earlier in my career I taught myself perl to enable me to create simple dynamic scripts that read data from flat files. This was a painful process to say the least since perl is known in some circles as a “write once, read never” language (my apologies to all the perl fanboys out there but I actually found lisp easier to learn than perl). So, without further delay, here’s a simple form written in Korn Shell:

——————————————————–

#!/bin/ksh

# Redirect stdin to get the form parms passed
PARM_PASSED=$(< /dev/stdin)

# Need to inform the browser it’s in HTML
print “Content-type: text/html”
print “”

# Process the form input
if [[ "$PARM_PASSED" != "" ]]
then
# Convert the ampersands to spaces for the ‘do’ loop
PARMS=`echo “$PARM_PASSED” | sed “s/&/ /g”`

for PARM in $PARMS
do
CLICKED=`echo “$PARM” | awk -F \= ‘{print $2}’`
print “You clicked: $CLICKED”
print “<br>”
done
fi

# Automatically refresh the page every five minutes

print “<html><head><meta http-equiv=”refresh” content=”300″><title>Test Korn shell CGI</title></head><body>”
print “<form action=\”/cgi-bin/korn_shell.cgi\” METHOD=\”POST\”>”

print “<font size=\”0\” face=\”Arial\”>”

print “<input type=\”checkbox\” name=\”host\” value=\”Test1\”><font color=$FGCOLOR>  Check the test box 1</font>”
print “<input type=\”checkbox\” name=\”host\” value=\”Test2\”><font color=$FGCOLOR>  Check the test box 2</font>”
print “<input type=\”checkbox\” name=\”host\” value=\”Test3\”><font color=$FGCOLOR>  Check the test box 3</font>”

print “<input type=\”submit\” value=\”Test Button\”>”

# Close it all down
print “</form>”
print “</font>”
print “</body></html>”

——————————————————–

Now let’s walk through this script and see what’s happening behind the scenes. First, we have the opening of most Korn Shells scripts:

#!/bin/ksh

This tells the O/S that we intend to execute this script against the Korn Shell. It’s always a good idea to put this in a script to make sure the default shell works for your script. Some UNIX variants, such as Linux, default to other shells. Although this script could easily be ported to other shells, it’s a bit much to detail here.

# Redirect stdin to get the form parms passed
PARM_PASSED=$(< /dev/stdin)

Since I don’t want to see the parameters passed in the URL of the browser, I chose to use the “POST” method of a form rather than the alternative “GET” method. Since I’m using this method the data returned to the script is neither a command-line parameter (e.g. $1, $2, etc) or an environment setting (e.g. REQUEST_URI=/cgi-bin/korn_shell.cgi?host=Test3). It’s passed to the shell script as STDIN in UNIX so I have to redirect it to a variable for subsequent parsing.

# Need to inform the browser it’s in HTML
print “Content-type: text/html”
print “”

Every web page originating from an executable directory has to begin with this to let the browser know the language (HTML) we’re speaking going forward.

# Process the form input
if [[ "$PARM_PASSED" != "" ]]
then
# Convert the ampersands to spaces for the ‘do’ loop
PARMS=`echo “$PARM_PASSED” | sed “s/&/ /g”`

for PARM in $PARMS
do
CLICKED=`echo “$PARM” | awk -F \= ‘{print $2}’`
print “You clicked: $CLICKED”
print “<br>”
done
fi

This loop goes through each parameter passed through the form input and processes a set of statements based on the input. This could be coupled with a function or an array (bearing in mind that Korn Shell has a limit of 1024 elements). In this case, we’re echoing the values back without HTML formatting to prove out the concept. The use of ’sed’ allows us to step through the list since there are no spaces allowed in the form input stream to STDIN.

# Automatically refresh the page every five minutes
print “<html><head><meta http-equiv=”refresh” content=”300″><title>Test Korn shell CGI</title></head><body>”
print “<form action=\”/cgi-bin/korn_shell.cgi\” METHOD=\”POST\”>”

Again, proving out a concept here. Auto-refresh is something that’s common in web pages and it works here as well. We’re also telling the web page what script to execute when we submit our selections. Since it’s the same script it will come back here.

print “<font size=\”0\” face=\”Arial\”>”

Setting up the default font for the page.

print “<input type=\”checkbox\” name=\”host\” value=\”Test1\”><font color=$FGCOLOR>  Check the test box 1</font>”
print “<input type=\”checkbox\” name=\”host\” value=\”Test2\”><font color=$FGCOLOR>  Check the test box 2</font>”
print “<input type=\”checkbox\” name=\”host\” value=\”Test3\”><font color=$FGCOLOR>  Check the test box 3</font>”

Here we’re setting up the checkboxes we see on the form. Notice how quotes must be escaped using the backslashes for proper interpretation by the shell.

print “<input type=\”submit\” value=\”Test Button\”>”

This part shows us the submit button at the bottom of the form.

# Close it all down
print “</form>”
print “</font>”
print “</body></html>”

Notice how the entire web page is considered a form. This is a simple method to ensure form elements can be placed anywhere on the page.

There are a couple of other things that must be in place for this to work as a web page. First, this script must be in a directory (typically cgi-bin) that the web server considers safe for executable scripts. Second the permissions in UNIX must be set correctly (775 or 755 is common).

Hopefully this has been a good tutorial on how to write simple web pages using a UNIX shell. I just wish I had seen this type of example a few years ago. Although, learning the basics of a new language is never a bad thing I much prefer writing it in Korn Shell.

Thanks for looking.

Michael Jenkins