Quick
lessons on shell programming
How to start writing
your own shell scripts
Summary
The various Unix shells can be used for programming as well as
simply interpreting commands. This month we get you started
with shell programming, showing you first how to define shell
functions and then how to tap into their power by integrating
them into shell scripts. (2,000 words)
T
he Unix shell in its various incarnations, the Bourne
Shell (sh ), the Korn Shell (ksh ), the
C Shell (csh ), the Bourne Again Shell (bash ),
is a powerful programming tool.
Although most people are familiar with the ability of the
shell to interpret commands as they are typed in at the
terminal, many are not familiar with its ability to execute
programs or shell scripts. Even more people are not familiar
with all of the tools available in a shell script.
The tools that can be used to create a shell script program
are all built into the shell -- whichever one you are using --
but they are rarely used in single command lines that are typed
in at the terminal.
Functions are a powerful feature of shell programming for the
the Bourne Shell and its derivatives, Korn Shell and bash .
For these exercises type ksh to start the Korn
shell and press Enter. If an error occurs then type sh
to start the Bourne shell and press Enter.
A function is a single command that can be defined to stand
in for one or more Unix commands. Using a function involves two
steps: defining the function and then invoking or executing the
function.
The first safe step to take is to check if the function name
that you intend to use is currently in use. In this case you are
going to create a function named "greetings." Type
greetings and press Enter. You should receive a message that
greetings could not be found. If this is not the case, then
select another command such as "hi_there" until you
find one that is not found:
greetings
ksh: greetings: not found
To define a function give the function a standard Unix-type
name, in this case greetings, followed by the definition of the
function. There are two different versions of the syntax for
defining a function. In the example below, either command will
define a function named greetings that prints "Hello
there" on the screen:
$ function greetings { echo Hello there ; }
$ greetings () { echo Hello there ; }
Type in either command, and you will notice that nothing appears to
happen. All you have done is define the function, but you have not
yet executed it. To execute the function, type its name just as you
would a standard Unix command. The function will execute:
$ greetings
Hello there
$
Expand on this a bit and define the function to include
displaying the environment variable containing the user I.D.:
$ greetings () { echo Hello there $LOGNAME ; }
Now when you type greetings, the message is more personalized.
$ greetings
Hello there mjb
$
A function may be defined to execute multiple commands by
separating the commands with a semi-colon or a newline. The
examples below both define a function named "whatdo"
that will list processes started by the current user. The ps
-ef command is piped in grep to search for
lines containing the user id ($LOGNAME) and the result is piped
through more . At the end of the display "Press
Enter" is displayed and a dummy variable is read from the
keyboard until the user presses Enter. These examples use the
two different syntaxes for defining a function. Note that in the
second version, a newline is used to replace each semi-colon,
and after each new line the continuation prompt (>) is
displayed:
$ whatdo () { ps -ef|grep $LOGNAME|more ; echo Press Enter ; read x ; }
or
$ function whatdo {
> ps -ef|grep $LOGNAME|more
> echo Press Enter
> read x
> }
$
Now type whatdo , and you will see a display of
your activities:
$ whatdo
mjb 260 1 7 Jul 31 01 0:04 -ksh
mjb 261 1 0 Jul 31 02 0:01 -ksh
mjb 2293 1 0 10:31:37 03 0:01 -ksh
mjb 2313 260 7 10:45:06 01 0:00 ps -ef
mjb 2314 260 7 10:45:06 01 0:00 grep mjb
mjb 2315 260 7 10:45:06 01 0:00 more
Press Enter
$
Integrating functions into shell
scripts
While functions are fine on the command line, their true power
comes about in shell scripts.
First some rules about shell scripts. Ensure that any shell
script you create will run using /bin/sh or /bin/ksh
by starting the shell script in one of two ways:
- Always start with a blank line.
- Always start with the line
#! /bin/sh or #!
/bin/ksh
The first method will work on older versions of Unix. The
second method has been supported on many versions of Unix for
several years now.
In the following examples, I will use the second version.
In the examples I have shown you so far, functions are used
to create a sort of alias for one or more other commands. Within
shell scripts, functions are used to tidy up the script so that
it is more readable and to avoid having to repeat the same logic
over and over. It frequently makes the logic of a long shell
script easier to follow.
In Listing 1 I have added line numbers to simplify the
explanation. You can type this in as simpmenu using
vi or some other editor. Then change the execution status with chmod
a+x simpmenu .
At lines 4 through 20 a long function named amenu()
is defined. This function clears the screen and displays a set
of prompts in a menu format. Lines 24 through 27 define a PressEnter()
function that asks the user to press ENTER and then waits for a
key press.
Lines 29 through 44 define functions that are to be used or
called in response to each menu pick. Note that each of these
three functions uses a call to PressEnter within
the body of the function. This ability to use a function inside
another function makes programming much easier. Without this
ability, the logic of the PressEnter function would
have to be fully typed in each time within the body of the three
main functions that are executed by the menu.
Up until line 63, no actual program has been run. If the
shell script stopped at this point, nothing would have happened.
At line 63 the program begins with a permanent loop (while true)
that runs to line 85. The menu is displayed by calling the
function amenu at line 66. The read command is used
to read the variable answer at line 69. At line 74, a case
statement tests the value in $answer and executes
one of the three defined functions based on the user's choice or
issues a break command that breaks out of the permanent loop.
Listing 1: A simple demonstration of
functions
1. #! /bin/ksh
2. # simpmenu, A very simple menu
3.
4. # amenu() defines a function to display a simple menu
5. amenu () {
6. # clear the screen
7. clear
8. echo `date`
9. echo
10. echo "\t\t\tMy Personal Menu"
11. echo
12. echo "\t\tPlease Select:"
13. echo
14. echo "\t\t\t 1. Directory display"
15. echo "\t\t\t 2. Current Activity"
16. echo "\t\t\t 3. Who is logged on"
17. echo "\t\t\t"
18. echo "\t\t\t 0. Exit"
19. echo Select by pressing a number and then ENTER ;
20. }
21.
22. # A function that asks the user to press enter
23. # and waits for the ENTER Key
24. PressEnter () {
25. echo Press Enter
26. read x
27. }
28.
29. # A function for each of the menu picks
30. DirectoryDisplay () {
31. ls -l|more
32. PressEnter
33. }
34.
35. CurrentActivity ()
36. {
37. ps -ef|more
38. PressEnter
39. }
40.
41. WhoIsLoggedOn () {
42. who|more
43. PressEnter
44. }
45.
46. # The main logic for the program displays the menu
47. # gets the users entry and initiates the activity
48. #------------------------------------------------------
49. # MAIN LOGIC
50. #------------------------------------------------------
51. # Every thing up to this point has
52. # just defined functions
53. # The program actually starts running here.
54.
55. # Repeat the menu over and over
56. # Steps are:
57. # 1. Display the menu
58. # 2. 'read' a line of input from the key board
59. # 3. Check the answer for 1, 2, 3 or 0 and dispatch
60. # to the appropriate function or exit
61. # 4 Repeat until 0 is entered
62.
63. while true
64. do
65. # 1. display the menu
66. amenu
67.
68. # 2. read a line of input from the keyboard
69. read answer
70.
71. # 3. Execute one of the defined functions based on the
72. # number entered by the user.
73.
74. case $answer in
75. 1) DirectoryDisplay ;;
76. 2) CurrentActivity ;;
77. 3) WhoIsLoggedOn ;;
78.
79. # If the user selects 0 to exit then break out
80. # of this loop
81. 0) break ;;
82. esac
83.
84. # Do it again until the user enters 0.
85. done
86.
87. # Clear the screen on the way out
88. clear
Listing 2 is the same activity but without functions. It is
much harder to read and contains a lot of duplicate code.
Listing 2: The non function version
of listing 1
1. #! /bin/ksh
2. # simpmenu, A very simple menu
3.
4.
5. # The main logic for the program displays the menu
6. # gets the users entry and initiates the activity
7. #------------------------------------------------------
8. # MAIN LOGIC
9. #------------------------------------------------------
10.
11. # Repeat the menu over and over
12. # Steps are:
13. # 1. Display the menu
14. # 2. 'read' a line of input from the key board
15. # 3. Check the answer for 1, 2, 3 or 0 and dispatch
16. # to the appropriate function or exit
17. # 4 Repeat until 0 is entered
18.
19. while true
20. do
21. # 1. display the menu
22. # clear the screen
23. clear
24. echo `date`
25. echo
26. echo "\t\t\tMy personal menu"
27. echo
28. echo "\t\tPlease Select:"
29. echo
30. echo "\t\t\t 1. Directory display"
31. echo "\t\t\t 2. Current Activity"
32. echo "\t\t\t 3. Who is logged on"
33. echo "\t\t\t"
34. echo "\t\t\t 0. Exit"
35. echo Select by pressing a number and then ENTER
36.
37. # 2. read a line of input from the keyboard
38. read answer
39.
40. # 3. Execute commands based on the
41. # number entered by the user.
42.
43. case $answer in
44. 1)
45. ls -l|more
46. echo Press Enter
47. read x ;;
48. 2)
49. ps -ef|more
50. echo Press Enter
51. read x ;;
52. 3)
53. who|more
54. echo Press Enter
55. read x ;;
56.
57. # If the user selects 0 to exit then break out
58. # of this loop
59. 0) break ;;
60. esac
61.
62. # Do it again until the user enters 0.
63. done
64.
65. # Clear the screen on the way out
66. clear
67.
Use functions to tidy up long shell scripts and you will be
taking advantage of one of the powerful features of the shell
programming language.
Contact
us for a free consultation. |