Entering and leaving the shell
In this section we look at the command sh - the
shell. As we have discussed, the shell is a program. It is treated
just as any other utility, and as such can take arguments. If it
takes one filename as its argument, the action taken is to take its
input (the commands for that shell) from that file, which is called
a shell script. With no arguments, the shell reads
its commands from the standard input. When a shell terminates, just
like any other command it returns an exit status, which is normally
the status of the last command executed by that shell. Create a
file (mycommand , say), containing a single line which
is the shell command false . Run the command and check
its exit status using $? :
$ sh mycommand
$ echo $?
1
Add an extra line, which is the shell command true ,
to the end of mycommand (using vi or
>> ) which is the shell command
true ; run the command again and check the exit status.
This time it will be 0.
A shell can be forced to terminate with a specific exit status
by means of command exit . It is good practice
explicitly to use exit to leave a script, rather than
allowing a default exit status. Add the following line to the end
of mycommand , run it again and see what exit status
you then get:
exit 42
Any commands that might be executed after an exit
command are discarded; exit kills the shell
immediately. The same is true of an interactive shell.
Type sh to start a new interactive shell, and reset
the prompt (so you know which is the new shell, and which the
previous one) then type exit followed by a number. You
will see that the new shell terminates (since you are back to the
original prompt), and $? confirms that the new shell
did indeed return an exit status to the original shell.
$ sh
$ PS1="--> "
--> exit 99
$ echo $?
99
Worked example
Write a script called morning to exit with exit
status 0 (if it is run before noon) and status 1 (if run after
noon).
Solution: Use date to check the time,
then test to check whether the time is am or pm.
HOUR=$( date +"%H" ) # HOUR is a number between 0 and 23
if [ $HOUR -le 11 ] # Check HOUR is AM
then exit 0 # ... then exit with status 0
else exit 1 # ... otherwise status 1
fi
This command can then be used, for instance, in the following
manner:
$ if sh morning
> then echo "Good morning"
> else echo "Good afternoon"
> fi
You could have piped the output from date to
cut instead of using the formatting option to
date , as in previous worked examples. By now, however,
you should be getting into the habit of using man to
find out more information on commands.
The shell supports various options, just like
other commands. A very useful option is -x ('eXpand'),
which instructs the shell that, each time it is about to execute a
command, it should display on the standard error stream the name of
that command. This is performed after all variable names have been
replaced by their values, and other substitutions done; it is thus
a very good method of debugging shell scripts in
the event of them not working as planned. For instance, supposing
file badcommand contains:
date # This is OK ...
cat $LOGNAME # but file chris doesn't exist
We could then run this with option -x set:
$ sh -x badcommand
+ date
Mon Dec 10 17:39:52 GMT 2001
+ cat chris
cat: chris: No such file or directory
Shell options can be set during a shell session by means of the
command set:
$ set -x
and can be unset as follows:
$ set +x
Within a script - or indeed when using an interactive shell -
you can set the positional parameters $1 ,
$2 , etc., without passing them as arguments to the
script. This uses set , and in the same way as before.
Suppose we have a file testfile , which contains a
script. Having set -x at the start of the file and
executing the file using sh would be equivalent to not
having set -x in the script, and running the script
with sh -x testfile . If we wanted to pass other
arguments to testfile , we could either have:
$ sh testfile arg1 arg2
arg3
or we could set the extra arguments at the start of
the script with
set arg1 arg2 arg3
in which case $1 would become arg1 ,
$2 would become arg2 , $3
would become arg3 and $# would become
3 . This is handy when debugging scripts that use
positional parameters. After setting positional parameters, you can
list what they are, together with the values of all other
environment variables, by just typing set . You can
unset all of them with:
$ set --
Try the following:
$ set --
$ set Chris
$ echo Hello $1
Hello Chris
$ set Sam
$ echo Hello $1
Hello Sam
The line set Sam has reset the value of the first
positional parameter $1 to Sam .
|