Functions

Any good programming language is going to give the ability to segment our code into manageable bite-size chunks.

The shell gives us this functionality in the form of functions. The syntax of a function is:

function name()
{
}
            

The word 'function' is optional, and the function will work equally well without it. Inside the function can be any command that you have thus far used in your shell scripts.

Below, I create a function within our shell called lscd. As you can see from this script, it will mount a cdrom, list it's contents, unmount it and finally eject it. In order to run this function, you will require a cdrom disk.

Pop it into your cdrom drive and then run the function lscd on the command line. We've created a new 'command'.

This lscd command is now like any other command on our system except it is a function. This function will only exist for the duration of this shell. So if you exit this shell, then your function is gone.

function lscd()
{
	mount /dev/cdrom
	ls -l /dev/cdrom
	umount /dev/cdrom
	eject /dev/cdrom
}
            

Now we saw the idea of sourcing scripts earlier on, but we can create a file called functions.sh and inside the file we can include all our functions.

We should not put need to put an 'exit 0' in any of them. Why? Since these are not scripts, they are only functions, an exit 0 will exit the current shell, which if sourced from the command line, closes your terminal.

Remember too that the functions within functions.sh need not be related in ANY way.[23]

Once we have our functions within the functions.sh file, we simply source the file each time we need a function defined there:

. functions.sh
            

Functions are quite simple; that's all there is to them.

How about passing parameters to a function? Well, perhaps we want to pass a parameter into the function. Our parameters become $1, $2 et cetera, the same way they were in the shell.

Let's look at an example of this usage:

function lscd()
{
	DEVICE=$1
	mount $DEVICE
	ls -l $DEVICE 
	umount $DEVICE
	eject $DEVICE
}
            

So we could test the functionality of this script with any of the statements below:

lscd /dev/cdrom
lscd /dev/fd0
lscd /dev/sda1
            

Parameters in a function and parameters to a script are identical in how we can use them. We can shift them, set them, assign them to variables, etc. In fact, everything we could do with a scripts parameters on the command line we can do within a function.

This provides us with some useful abilities in terms of segmenting our code thus creating code that is easily maintainable.

Remember that if we include an exit status at the end of our function, then we will exit out of our current shell, so don't do it!

We'll discuss the return built-in shortly.

Once we've actually created our function, how do we unset it or uncreate it or remove it?

Well, we could either exit out of our shell or we could unset it, for example:

unset lscd
            

The final thing about functions is that often we need to know what the exit status of the function was. In other words, did it complete successfully or did it fail? What was the exit status? While we can't use an 'exit', we can use a 'return'. The same rules apply as before.

A return value of 0 means that the function completed correctly. A non-zero return value means the function did not complete correctly. Given our lscd function, we now want to run the following on the command line:

lscd /dev/cdrom
echo $?
            

Recall that $? will show the exit status of the previous command, which happens to be lscd in our case. Because we return a value of 0 from lscd, the exit status from lscd is 0. It's a good idea to have a return value to every function, just as it is a good idea to have exit status to every script.

I will rewrite my lscd function as follows:

function lscd()
{
	mount /dev/cdrom
	ls -l /dev/cdrom
	umount /dev/cdrom
	eject /dev/cdrom
	return 0
}
            

Exercises:

With your newfound knowledge of functions, write the following scripts.

  1. Modify your script from earlier, which showed the disk space and memory in HTML format. Only this time, ensure that each of these tasks are separated into individual functions.

  2. Write a function that may be used on the command line, which will show your hardware address, IP address and default gateway on your machine.

  3. I often need to change between a DHCP and a static address, and this provides a source of stress for me as each time I need to modify the files, restart the network, etc. Write a function that I can run on the command line that will prompt me for all the manner of my network configuration. It should ask whether we require DHCP / static addressing and if static is selected, it should require us to enter the IP address, the netmask, the default gateway and the DNS server(s). Ensure that the function will restart the necessary services once we have chosen our method of network settings.

Challenge sequence

  1. For this sequence, you will need to obtain some knowledge on a very useful graphing program called gnuplot. Although it might look difficult, once you have the hang of it, it can do some really nice graphs, and of course make you look like a genius.

  2. Write a function that will ping up to 4 hosts a maximum of 10 times per hosts and plot the response times on a graph. Ensure that this graph is available from a web-page called index.html



[23] Using functions is is how RedHat, SuSE and other Linux vendors implement their rc scripts to start and stop services.