Executing Korn Shell Scripts





Executing Korn Shell Scripts

Let's make a Korn shell script out of the print Hello world command by putting it into a file like this:

$ print "print Hello world" >prhello 

Before Korn shell scripts can be executed, they must be made executable by setting the execute and read bits with the chmod command:

$ chmod 755 prhello 

or

$ chmod +rx prhello 

Assuming that the current directory is in the search path $PATH, prhello can now be executed by simply invoking it by name:

$ prhello 
Hello world 

Korn shell scripts can also be executed by invoking them as the first argument to ksh:

$ ksh prhello 
Hello world 

Now we can use prhello like any other command. The output can be directed to a file:

$ prhello >p.out 
$ cat p.out 
Hello world 

It can be used with a pipe:

$ prhello | wc 
1      2     12 

or with command substitution:

$ print "We always say \"$(prhello)\"" 
We always say "Hello world" 

By default, Korn shell scripts are run in a separate environment. This means that variables from the current environment are not available to Korn shell scripts unless explicitly exported, and variables defined in Korn shell scripts are not passed back to the parent shell. Just to prove it, here is a demonstration. The checkvar Korn shell script does just one thing: it prints the value of LOCALVAR.

$ cat checkvar 
print "LOCALVAR is set to: $LOCALVAR" 

If LOCALVAR is set to something in the current environment, and checkvar is run, we see that LOCALVAR is not defined:

$ LOCALVAR="This is the original value" 
$ checkvar 
LOCALVAR is set to: 

If we export LOCALVAR, then its value will be available to checkvar:

$ typeset —x LOCALVAR 
$ checkvar 
LOCALVAR is set to: This is the original value 

To show that Korn shell script environments cannot modify variable values in the parent shell, we'll change checkvar to reassign a value to LOCALVAR.

$ cat checkvar 
print "LOCALVAR is set to: $LOCALVAR" 
LOCALVAR="This is a new value" 
print "The new LOCALVAR is set to: $LOCALVAR" 

Now when it is run, LOCALVAR is set to the new value:

$ checkvar 
LOCALVAR is set to: This is the original value 
The new LOCALVAR is set to: This is a new value 

Meanwhile, back in the parent shell, LOCALVAR has not been affected.

$ print $LOCALVAR 
This is the original value 

If the allexport option is enabled (set –a, or set ?o allexport), variables are automatically exported when defined. By default, this option is disabled.

Positional Parameters

Positional parameters are special variables used to keep track of arguments to the Korn shell, scripts, and functions. Positional parameter names contain only digits and cannot be set directly using variable=value syntax. By default, parameter zero (or $0) is set to the name of the shell, script or function.

$ print $0 
/bin/ksh 

The remaining parameters 1 to n are set to each of the arguments passed to the shell, script or function. For example, if you invoke a Korn shell script called ptest and pass the arguments A, B, and C, then in the script ptest, $0 would be set to ptest, $1 to A, $2 to B, and $3 to C.

Positional Parameters

$0

name of script or function or pathname of Korn shell for set

$n

nth argument to script, function, or set

${n}

nth argument to script, function, or set when n is greater than 9

$#

number of positional parameters

$*, $@

all positional parameters separated with a blank

"$*"

all positional parameters enclosed in double quotes

${*:X}

all X to the last positional parameters

"${*:X}"

all X to the last positional parameters enclosed in double quotes

${*:X:n}

n positional parameters beginning with Xth

"${*:X:n}"

n positional parameters beginning with Xth enclosed in double quotes

graphics/08fig01.gif

There are three special Korn shell variables that provide information about the current positional parameters. The first is $#, and it contains the number of positional parameters. The other two are $@ and $*, and they both contain all the positional parameters. So in the above ptest example, $# would be 3, and both $* and $@ would be A B C. Here is a Korn shell script that manipulates positional parameters. It displays the name of the current script, the number of positional parameters, and the value of each of the positional parameters:

$ cat check_params 
print "Script name:              $0" 
print "Number of args passed:    $#" 
print "Arguments passed:         $*" 
print "Arg 1=$1, Arg 2=$2, Arg 3=$3" 

If executed with no arguments, this is the output:

$ check_params 
Script name:              check_params 
Number of args passed:    0 
Arguments passed: 
Arg 1=, Arg 2=, Arg 3= 

while if executed with the arguments A and B, the output is:

$ check_params A B 
Script name:              check_params 
Number of args passed:    2 
Arguments passed:         A B 
Arg 1=A, Arg 2=B, Arg 3= 
Modifying Positional Parameters

By default, $0 is set to the name of the shell, script or function. It cannot be set or modified. The remaining parameters from $1 to $n can be reassigned with the shift command.

The shift command, with no arguments, shifts positional parameters left once, so that $1 takes the value of $2, $2 takes the value of $3, and so on. The original value of $1 is lost.

Let's change the check_params script so that it shifts the positional parameters left once:

$ cat check_params 
print "Script name:              $0" 
print "Number of args passed:    $#" 
print "Arguments passed:         $*" 
print "Arg 1=$1, Arg 2=$2, Arg  3=$3" 
shift 
print "Number of remaining args: $#" 
print "Remaining args:           $*" 
print "Arg 1=$1, Arg 2=$2, Arg 3=$3" 

When we run it again with the arguments A B, we get:

$ check_params A B 
Script name:                     check_params 
Number of args passed:           2 
Arguments passed:                A B 
Arg 1=A, Arg 2=B, Arg 3= 
Number of remaining args:        1 
Remaining args:                  B 
Arg 1=B, Arg 2=, Arg 3= 

After the shift command, $1 is set to B and $2 is unset. The original value of $1 is lost.

The positional parameters can be shifted left more than once by providing an integer argument to the shift command: shift n.

Now let's try something else with positional parameters. Here is a Korn shell script called kuucp. It uses uucp to copy a file to the public directory on the rnihd system.

$ cat kuucp 
PUBDIR=${PUBDIR:?usr/spool/uucppublic} 
uucp $1 rnihd!$PUBDIR/$1 
print "Copied $1 to rnihd!$PUBDIR/$1" 

So instead of typing this long command line:

$ uucp n.out rnihd!/usr/spool/uucppublic/n.out 

we can do this:

$ kuucp n.out 

and in the script, $1 gets substituted with n.out in both the source and target file arguments. We could extend this further to be able to uucp files to any system by having a system name given as another command-line argument. Now $1 is used for the source and target file, and $2 for the remote system name.

$ cat kuucp 
PUBDIR=${PUBDIR:?usr/spool/uucppublic} 
uucp $1 $2!$PUBDIR/$1 
print "Copied $1 to $2!$PUBDIR/$1" 

To send the file msg.c to the uucp public directory on the unisf system, kuucp would be invoked like this:

$ kuucp msg.c unisf 

$1 would be substituted with the msg.c, and $2 with unisf. Notice that the destination directory is taken from PUBDIR variable. If it's not set, the default uucp public directory is used.

The exit command

In Chapter 2, we learned that Unix programs return an exit status. And that a zero exit status indicates successful execution, while a non-zero exit status indicates failure. The exit command allows you to terminate execution from anywhere in a Korn shell script and return an exit value using this format:

exit 

or

exit n 

where n is the exit status to return. If n is not specified, the exit status of the previous command is used. If you don't use exit, then scripts finish after the last command is executed.

Take a look at the kuucp script again. What happens if an error occurs? For example, if the file argument is entered incorrectly, or it doesn't exist? The uucp command will fail, but the status message following will still get displayed. Here is a good place for exit. It could be used to terminate execution and return a non-zero exit status if for some reason the uucp command failed. To get the exit status, $? is checked after uucp is run. If it is non-zero, then we display our own error message and exit. Otherwise, the next command is executed and the script terminates successfully.

$ cat kuucp 
PUBDIR=${PUBDIR:?usr/spool/uucpublic} 
uucp $1 $2!$PUBDIR/$1 2>&?/span> 
(($? != 0)) && {print "Got uucp error"; exit 1;} 
print "Copied $1 to $2!$PUBDIR/$1" 

By the way, the 2>&?/span> just traps the uucp error messages. We don't need to see them anymore, since kuucp is now doing its own error processing. Now when kuucp is run on a non-existent file, this is what happens:

$ kuucp nofile unisf 
Got uucp error 
$ print $? 
1 

The exit command does one more thing. If given at the command prompt, it terminates your login shell.



     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows