You are on page 1of 32

The Linux Shells Creating a Script

Operating Systems Laboratory Amir Saman Memaripour

A Simple Shell Script


By convention, Bash shell scripts have names ending with .sh. # hello.sh # This is my first shell script printf Hello! Bash is wonderful. exit 0

Comments
Lines beginning with number signs (#) are comments. They are notes to the reader and do not affect the execution of a script. Everything between the number sign and the end of the line is effectively ignored by Bash.

Running Your Script


The exit command, followed by a zero, informs the program running your shell script that the script ran successfully. You can run your script by starting a new shell: $ bash hello.sh If there are no mistakes, Bash responds with this message: Hello! Bash is wonderful.!

Creating a Well-Behaved Script


Suppose your job is to write a shell script to run the sync command when there are no users on the system. The following commands are adequate to do the job. $USERS=`who | wc -l` if [ $USERS -eq 0 ] ; then sync fi

Creating a Well-Behaved Script


This works suitably well at the Bash prompt. But consider the following questions:

How does Linux know that this is a Bash script? If there is more than one who command on the computer,
which one executes?

How does the script inform the program that runs it if it


succeeds or fails?

What happens if the sync command was accidentally


deleted or if permissions? the system administrator altered the

Creating a Well-Behaved Script


Bash is a very flexible language: It needs to be if it is going to be used interactively. But in script writing, this flexibility can lead to security loopholes and unexpected behavior. For a shell script to be well-behaved, it has to do more than simply execute the same commands typed at the Bash dollar prompt.

Creating a Well-Behaved Script


A well-structured Bash script can be divided into five sections:

The header Global declarations Sanity checks The main script Cleanup
Each of these sections plays an important role in the design of a script. Next, you take a look at the previous example and see how you can improve it by examining each of the sections.

Assignment (5 points)
Write a shell script to evaluate the execution time of some specified tasks in seconds. Deadline: November 27th, 10:00 AM How to Via email to memarypour@gmail.com This assignment is mandatory! deliver?!

The Header
The header defines what kind of script this is, who wrote it, what version it is, and what assumptions or shell options Bash uses. The very first line of a script is the header line. This line begins with #! at the top of the script, flush with the left margin. This character combination identifies the kind of script. Linux uses this information to start the right program to run the script. For Bash scripts, this line is the absolute pathname indicating where the Bash interpreter resides. On most Linux distributions, the first header line is as follows #!/bin/bash

10

Global Declarations
All declarations that apply to the entirety of the script should occur at the top of the script, beneath the header. By placing global declarations in one place, you make it easy for someone to refer to them while reading the script. declare -rx who=/usr/bin/who # the who command - man 1 who declare -rx sync=/bin/sync # the sync command - man 1 sync declare -rx wc=/usr/bin/wc # the wc command - man 1 wc

11

Sanity Checks
The next section, sanity checks, protects the script from unexpected changes in the computer. Normally, when a command runs at the command prompt, Bash searches several directories for the command you want to run. If it cant find the command, perhaps because of a spelling mistake, Bash reports an error. This kind of behavior is good for working interactively with Bash because it saves time and any mistakes are easily corrected with a few keystrokes.

12

Sanity Checks
Scripts, on the other hand, run without any human supervision. Before a script executes any statements, it needs to verify that all the necessary files are accessible. All required commands should be executable and stored in the expected locations. These checks are sometimes called sanity checks because they do not let the script begin its main task unless the computer is in a known, or sane, state. This is especially important with operating systems such as Linux that are highly customizable: What is true on one computer might not be true on another.

13

Sanity Checks
Sometimes system administrators unintentionally delete or change the accessibility of a file, making it unavailable to a script. Other times, changes in the environment can change which commands are executed. Malicious computer users have also been known to tamper with a persons login profile so that the commands you think you are running are not the ones you are actually using. In the case of the sample script, you need to verify that the commands you need are where theyre supposed to be and are available to the script.

14

Sanity Checks
# Sanity checks if test -z $BASH ; then printf $SCRIPT:$LINENO: please run this script exit 192 fi if test ! -x $who ; then printf $SCRIPT:$LINENO: the command $who is not exit 192 fi

15

The Main Script


When you have verified that the system is sane, the script can proceed to do its work. # Flush disks if nobody is on the computer USERS=`who | wc -l` if [ $USERS -eq 0 ] ; then sync fi

16

Cleanup
Finally, the script needs to clean up after itself. Any temporary files should be deleted, and the script returns a status code to the person or program running the script. In this case , there are no files to clean up. More complex scripts might use a variable to keep track of that status code returned by a failed command. By placing the cleanup section at the end of the program, there is one unique place to perform your housekeeping tasks, as opposed to duplicating them throughout the script. exit 0 # all is well

17

Stopping a Script
The logout command, which ends an interactive login session, cannot be used to stop a script. (After all, a script is not a login session.) Instead, Bash provides two built-in commands for terminating a script. As seen previously, the exit command unconditionally stops a script. exit can include a status code to return to the caller of the script. A status code of 0 indicates no error. If the status code is omitted, the status of the last command executed by the script is returned. As a result, its always best to supply an exit status. exit 0 # all is well

18

Stopping a Script
A script automatically stops when it reaches its end as if there was an implicit exit typed there, but the exit status is the status of the last command executed. The suspend command likewise unconditionally stops a script. However, unlike exit, execution is suspended until the script is signaled to wake up and resume the next statement after the suspend command. suspend # wait until notified otherwise

19

Stopping a Script
There is also a Linux utility called sleep. Sleep suspends the script for a specific number of seconds after which it wakes up and resumes the next statement after the sleep command. sleep 5 # wait for 5 seconds Sleep is useful for placing pauses in the script, enabling the user to read whats been displayed so far. Sleep isnt suitable for synchronizing events, however, because how long a particular program runs on the computer often depends on the system load, number of users, hardware upgrades, and other factors outside of the scripts control.

20

Reading Keyboard Input


The built-in read command stops the script and waits for the user to type something from the keyboard. The text typed is assigned to the variable that accompanies the read command. printf Archive files for how many days? read ARCHIVE_DAYS

21

Reading Keyboard Input


In this example, the variable ARCHIVE_DAYS contains the number of days typed by the user. There are a number of options for read. First, -p (prompt) is a shorthand feature that combines the printf and read statements. read displays a short message before waiting for the user to respond. read -p Archive ARCHIVE_DAYS files for how many days?

22

Reading Keyboard Input


The -r (raw input) option disables the backslash escaping of special characters. Normally, read understands escape sequences such as \n when theyre typed by the user. Using raw input, read treats the backspace the same as any other character typed on the keyboard. You need to use -r only when you need to handle the backslash character yourself. read -p Enter a Microsoft Windows (backslashes allowed): -r MS_PATH pathname

23

Reading Keyboard Input


A timeout can be set up using the -t (timeout) switch. If nothing is typed by the end of the timeout period, the shell continues with the next command and the value of the variable is unchanged. If the user starts typing after the timeout period ends, anything typed is lost. The timeout is measured in seconds. read -t 5 FILENAME # wait up to 5 seconds to read a filename

24

Reading Keyboard Input


A limit can be placed on the number of characters to read using the -n (number of characters) switch. If the maximum number of characters is reached, the shell continues with the next command without waiting for the Enter/Return key to be pressed. read -n 10 FILENAME # read no more than 10 characters If you dont supply a variable, read puts the typed text into a variable named REPLY. Well-structured scripts should avoid this default behavior to make it clear to a script reader where the value of REPLY is coming from.

25

Basic Redirection
You can divert messages from commands like printf to files or other commands. Bash refers to this as redirection. There are a large number of redirection operators. The > operator redirects the messages of a command to a file. The redirection operator is followed by the name of the file the messages should be written to. For example, to write the message The processing is complete to a file named results.txt, you use printf The processing is complete > results.txt

26

Basic Redirection
The > operator always overwrites the named file. If a series of printf messages are redirected to the same file, only the last message appears. To add messages to a file without overwriting the earlier ones, Bash has an append operator, >>.This operator redirects messages to the end of a file. printf The processing is complete > results.txt printf There were no errors >> results.txt

27

Basic Redirection
In the same way, input can be redirected to a command from a file. The input redirection symbol is <. For example, the wc (word count) utility gathers statistics about a file. To count the number of lines in a file, use wc lines < purchase_orders.txt wc lines treats the contents of purchase_orders.txt as if it were typed in from the keyboard.

28

Basic Redirection
Instead of files, the results of a command can be redirected as input to another command. This process is called piping and uses the vertical bar (or pipe) operator |. who | wc lines # count the number of users Any number of commands can be strung together with vertical bar symbols. A group of such commands is called a pipeline. If one command ends prematurely in a series of pipe commands, for example, because you interrupted a command with a control-c, Bash displays the message Broken Pipe on the screen.

29

Basic Redirection
The lines following a command can also be read and processed by the command. The operator << treats the lines following it in a script as if they were typed from the keyboard. The operator needs to be followed by a marker that denotes the end of the lines. wc IBM END_OF_LIST In this example, Bash treats the three lines between the END_OF_LIST markers as if they were being typed from the keyboard or read from a file embedded in the script. The line count returned by wc is 3. lines << Book Apple END_OF_LIST

30

Basic Redirection
The data in the << list is known as a here file (or a here document) because the word HERE was often used in Bourne shell scripts as the marker word. Newer versions of Bash have another here file redirection operator, <<<, which redirects a single line of text.

31

32

You might also like