OnWorks Linux and Windows Online WorkStations

Logo

Free Hosting Online for WorkStations

< Previous | Contents | Next >

If you want, prompts can execute shell scripts and behave different under different conditions. You can even have the prompt play a tune every time you issue a command, although this gets boring pretty soon. More information can be found in the Bash-Prompt HOWTO.


image

7.2.5. Shell scripts


7.2.5.1. What are scripts?


A shell script is, as we saw in the shell configuration examples, a text file containing shell commands. When such a file is used as the first non-option argument when invoking Bash, and neither the -c nor -s option is supplied, Bash reads and executes commands from the file, then exits. This mode of operation creates a

non-interactive shell. When Bash runs a shell script, it sets the special parameter 0 to the name of the file, rather than the name of the shell, and the positional parameters (everything following the name of the script) are set to the remaining arguments, if any are given. If no additional arguments are supplied, the positional parameters are unset.


A shell script may be made executable by using the chmod command to turn on the execute bit. When Bash finds such a file while searching the PATH for a command, it spawns a sub-shell to execute it. In other words, executing


filename ARGUMENTS


is equivalent to executing


bash filename ARGUMENTS


if "filename" is an executable shell script. This sub-shell reinitializes itself, so that the effect is as if a new shell had been invoked to interpret the script, with the exception that the locations of commands remembered by the parent (see hash in the Info pages) are retained by the child.


Most versions of UNIX make this a part of the operating system's command execution mechanism. If the first line of a script begins with the two characters "#!", the remainder of the line specifies an interpreter for the program. Thus, you can specify bash, awk, perl or some other interpreter or shell and write the rest of the script file in that language.


The arguments to the interpreter consist of a single optional argument following the interpreter name on the first line of the script file, followed by the name of the script file, followed by the rest of the arguments. Bash will perform this action on operating systems that do not handle it themselves.


Bash scripts often begin with


#! /bin/bash (assuming that Bash has been installed in /bin), since this ensures that Bash will be used to interpret the script, even if it is executed under another shell.


image


7.2.5.2. Some simple examples


A very simple script consisting of only one command, that says hello to the user executing it:


[jerry@nowhere ~] cat hello.sh

#!/bin/bash

echo "Hello $USER"

[jerry@nowhere ~] cat hello.sh

#!/bin/bash

echo "Hello $USER"

The script actually consists of only one command, echo, which uses the value of ($) the USER environment variable to print a string customized to the user issuing the command.


Another one-liner, used for displaying connected users:


#!/bin/bash

who | cut -d " " -f 1 | sort -u

#!/bin/bash

who | cut -d " " -f 1 | sort -u

Here is a script consisting of some more lines, that I use to make backup copies of all files in a directory. The script first makes a list of all the files in the current directory and puts it in the variable LIST. Then it sets the name of the copy for each file, and then it copies the file. For each file, a message is printed:


tille:~> cat bin/makebackupfiles.sh

#!/bin/bash

# make copies of all files in a directory LIST=`ls`

for i in $LIST; do

ORIG=$i

DEST=$i.old

cp $ORIG $DEST echo "copied $i"

done

tille:~> cat bin/makebackupfiles.sh

#!/bin/bash

# make copies of all files in a directory LIST=`ls`

for i in $LIST; do

ORIG=$i

DEST=$i.old

cp $ORIG $DEST echo "copied $i"

done

Just entering a line like mv * *.old won't work, as you will notice when trying this on a set of test files. An echo command was added in order to display some activity. echo's are generally useful when a script won't work: insert one after each doubted step and you will find the error in no time.


The /etc/rc.d/init.d directory contains loads of examples. Let's look at this script that controls the fictive ICanSeeYou server:


#!/bin/sh

# description: ICanSeeYou allows you to see networked people


# process name: ICanSeeYou

# pidfile: /var/run/ICanSeeYou/ICanSeeYou.pid

# config: /etc/ICanSeeYou.cfg


# Source function library.

. /etc/rc.d/init.d/functions


# See how (with which arguments) we were called. case "$1" in

start)

echo -n "Starting ICanSeeYou: " daemon ICanSeeYou

echo

touch /var/lock/subsys/ICanSeeYou

;;

stop)

echo -n "Shutting down ICanSeeYou: "

#!/bin/sh

# description: ICanSeeYou allows you to see networked people


# process name: ICanSeeYou

# pidfile: /var/run/ICanSeeYou/ICanSeeYou.pid

# config: /etc/ICanSeeYou.cfg


# Source function library.

. /etc/rc.d/init.d/functions


# See how (with which arguments) we were called. case "$1" in

start)

echo -n "Starting ICanSeeYou: " daemon ICanSeeYou

echo

touch /var/lock/subsys/ICanSeeYou

;;

stop)

echo -n "Shutting down ICanSeeYou: "


killproc ICanSeeYou echo

rm -f /var/lock/subsys/ICanSeeYou

rm -f /var/run/ICanSeeYou/ICanSeeYou.pid

;;

status)

status ICanSeeYou

;;

restart)

$0 stop

$0 start

;;

*)

echo "Usage: $0 {start|stop|restart|status}" exit 1

esac


exit 0

killproc ICanSeeYou echo

rm -f /var/lock/subsys/ICanSeeYou

rm -f /var/run/ICanSeeYou/ICanSeeYou.pid

;;

status)

status ICanSeeYou

;;

restart)

$0 stop

$0 start

;;

*)

echo "Usage: $0 {start|stop|restart|status}" exit 1

esac


exit 0

First, with the . command (dot) a set of shell functions, used by almost all shell scripts in

/etc/rc.d/init.d, is loaded. Then a case command is issued, which defines 4 different ways the script can execute. An example might be ICanSeeYou start. The decision of which case to apply is made by reading the (first) argument to the script, with the expression $1.


When no compliant input is given, the default case, marked with an asterisk, is applied, upon which the script gives an error message. The case list is ended with the esac statement. In the start case the server program is started as a daemon, and a process ID and lock are assigned. In the stop case, the server process is traced down and stopped, and the lock and the PID are removed. Options, such as the daemon option, and functions like killproc, are defined in the /etc/rc.d/init.d/functions file. This setup is specific to the distribution used in this example. The initscripts on your system might use other functions, defined in other files, or none at all.


Upon success, the script returns an exit code of zero to its parent.


This script is a fine example of using functions, which make the script easier to read and the work done faster. Note that they use sh instead of bash, to make them useful on a wider range of systems. On a Linux system, calling bash as sh results in the shell running in POSIX-compliant mode.


Top OS Cloud Computing at OnWorks: