SLIDE 1
Shell Scripts
CS3411 Spring 2009
SLIDE 2 CS3411 Shell Scripts 2
Revisiting execve (2 )
NA ME execve -execut e p rog r am SYNOPSIS # i nc l ude <un i s t d .h> i n t execve ( cons t char * f i l ename, cha r * cons t a rgv[ ] , cha r * cons t envp [ ] ) ; DESCRIPTION execve( ) execut es t he p rog ram po in ted t
f i l e name. f i l ename mus t be e i t her a b i na r y execu t ab le ,
a s c r i p t s t a r t i ng wi t h a l i ne
t he f
" # ! i n t e rp re te r [ a rg ] " . I n t he l a t te r case , t he i n te rp re t e r mus t be a v a l i d pa thname f
an execu tab le wh i ch i s n
i t se l f a sc r i p t , wh i ch wi l l be i n voked as i n te rp r e te r [ a rg] f i l ename . . . .
SLIDE 3 CS3411 Shell Scripts 3
s c r i p t, protected 0755:
#!/bin/cat -A line one line two
- In keeping with the man page, invoke
/ b in / ca t
ca t s c r i p t.
% ./catscript #!/bin/cat -A$ line one$ line two$
- Suppose we have file named sc
r i p t, protected 0755, that starts with # ! / b i n / sh
- Line that starts with # is a comment to /bin/sh.
- The file sc
r i p tis then a shell script.
- If first line does not start with #
!, it is as if the first line were # ! /b i n / sh.
SLIDE 4 CS3411 Shell Scripts 4
Command Line Arguments
- Shell scripts can act like standard UNIX commands and take
arguments from the command line.
- Arguments are passed from the command line into a shell
program using the positional parameters $1 through $9. Each parameter corresponds to the position of the argument on the command line.
- The positional parameter $0 refers to the command name or
name of the executable file containing the shell script.
- All the positional parameters can be referred to using the special
parameter $*. This is useful when passing filenames as
- arguments. For example, p
r i n tps:
# This script converts ASCII files to PostScript # and sends them to the default (PostScript) printer mp $* | lpr
SLIDE 5 CS3411 Shell Scripts 5
- This processes the three files given as arguments to the
script/command printps:
./printps elm.txt vi.ref msg
- Usually only nine command line arguments can be accessed
using positional parameters. The sh i f tcommand gives access to command line arguments greater than nine by shifting each of the arguments.
- The second argument ($2) becomes the first ($1), the third ($3)
becomes the second ($2) and so on. This gives you access to the tenth command line argument by making it the ninth. The first argument is no longer available.
- Successive shift commands make additional arguments
- available. Note that there is no “unsh
i f t ” command to bring back arguments that have been shifted through $1!
SLIDE 6
CS3411 Shell Scripts 6
The shell script sh i f t _demo:
#!/bin/sh echo "arg1=$1 arg2=$2 arg3=$3" shift echo "arg1=$1 arg2=$2 arg3=$3" shift echo "arg1=$1 arg2=$2 arg3=$3" shift echo "arg1=$1 arg2=$2 arg3=$3"
In execution:
% ./shift_demo one two three four five six seven arg1=one arg2=two arg3=three arg1=two arg2=three arg3=four arg1=three arg2=four arg3=five arg1=four arg2=five arg3=six
SLIDE 7 CS3411 Shell Scripts 7
$ {3 :
fau l t }means $3, unless $3 is unset or null, then it means de fau l t .
#!/bin/sh echo "arg1=$1 arg2=$2 arg3=${3:-dummy}" % ./default_demo a b c arg1=a arg2=b arg3=c % ./default_demo a b arg1=a arg2=b arg3=dummy % ./default_demo a b "" arg1=a arg2=b arg3=dummy
$ {3
au l t }means $3 unless $3 is unset (skips null check)
#!/bin/sh echo "arg1=$1 arg2=$2 arg3=${3-dummy}" % ./default_demo a b c arg1=a arg2=b arg3=c % ./default_demo a b arg1=a arg2=b arg3=dummy % ./default_demo a b "" arg1=a arg2=b arg3=
SLIDE 8 CS3411 Shell Scripts 8
Special Shell Variables
- Some special shell variables:
– # is number of command line parameters ($# is its value) – $ is the pid of the shell ($$ is its value) – ? is decimal value returned by the last synchronously executed command – ! is pid of the last background command invoked
- Common use of $$: temp file names:
echo shell pid is $$ > sh.$$ % ./tempfile.demo % ls sh.* sh.524 % cat sh.524 shell pid is 524
SLIDE 9 CS3411 Shell Scripts 9
Variables and Quoting
- Double quotes suppresses meaning of all special characters
except: $ ` \ – ` is backquote (not ‘) – \ is escape
- Single quotes suppresses meaning of all special characters except ‘
[jmayo]$./special.sh
# # string string $VAR $VAR #!/bin/sh # echo # echo "#" echo '#' VAR=string echo $VAR echo "$VAR" echo "\$VAR" echo '$VAR'
SLIDE 10 CS3411 Shell Scripts 10
“Subshells”
- ( cmds ) – Combines stdout and stderr of cmds into one
stream – Launches another instance of command processor – Does not fork new process
[jmayo]$ cat newshell.sh #!/bin/sh ( echo alpha; echo beta ) | wc [jmayo]$ ./newshell.sh 2 2 11
SLIDE 11 CS3411 Shell Scripts 11
[jmayo]$ ./newshell2.sh First pid is 3249 Second pid is 3249
[jmayo]$ [jmayo]$ cat newshell2.sh #!/bin/sh echo First pid is $$ (echo Second pid is $$ ) echo ----------------------- ./echoPid.sh
[jmayo@]$ cat echoPid.sh
echo "Echo pid is $$"
SLIDE 12 CS3411 Shell Scripts 12
Variable Propagation
- Variables defined in shell are not visible in the parent
[jmayo]$ cat prop.sh #!/bin/sh VAR=value echo "First value is <$VAR>" (echo "Sub value is <$VAR>"; VAR=newvalue; \ echo "Sub new value is <$VAR>") echo "Final value is <$VAR>" [jmayo]$ ./prop.sh First value is <value> Sub value is <value> Sub new value is <newvalue> Final value is <value>
SLIDE 13 CS3411 Shell Scripts 13
Export
- Export moves variable definition from shell to environment
– Other programs may access
[jmayo]$ bash
bash-3.00$ VAR=value; ./echoVar.sh Echovar has value bash-3.00$ export VAR=value; ./echoVar.sh Echovar has value value bash-3.00$ exit [jmayo@asimov ~/codeExamples]$ setenv VAR value; ./echoVar.sh Echovar has value value [jmayo@asimov ~/codeExamples]$
SLIDE 14
CS3411 Shell Scripts 14
Reading Input
Can read from standard input into a shell script with the read command:
% cat readin.sh echo "Please enter your name:" read name echo "Hi, $name” % ./readin.sh Please enter your name: phil Hi, phil
SLIDE 15
CS3411 Shell Scripts 15
If there is more than one word in the input, each word can be assigned to a different variable. Any words left over are assigned to the last named variable. For example:
% cat readin2.sh echo "Please enter your surname" echo "followed by your first name:" read name1 name2 echo "Hi, $name2 $name1” % ./readin2.sh Please enter your surname followed by your first name: Nimble jack b Hi, jack b nimble
SLIDE 16 CS3411 Shell Scripts 16
Return Value of a Command
- Every Unix command returns a value on exit which the shell can
- interrogate. This value is held in the read-only shell variable ?.
- A value of 0 (zero) signifies success; anything other than 0
signifies failure.
- Unlike the C convention, 0 is essentially a true and non-zero is a
false.
- Use that value to have conditional control flow in shell scripts:
– the i fstatement – the && operator – the | |operator
SLIDE 17 CS3411 Shell Scripts 17
The i fCommand
i fstatement uses the exit status of the given command and conditionally executes the statements following. The general syntax is:
if test then commands (if condition is true) else commands (if condition is false) fi
then, e l se and f iare shell reserved words and as such are only recognized after a newline or ; (semicolon).
- Make sure that you end each if construct with a
f istatement.
SLIDE 18 CS3411 Shell Scripts 18
i fstatement may be nested:
if ... then ... else if ... ... fi fi
l i fstatement can be used as shorthand for an else if
if ... then ... elif ... ... fi fi
SLIDE 19
CS3411 Shell Scripts 19
An example:
% cat checkon.sh if finger | grep -s $1 > /dev/null then echo $1 is logged in else echo $1 not available fi % ./checkon.sh park park is logged in % ./checkon.sh sharon sharon not available
SLIDE 20 CS3411 Shell Scripts 20
The && Operator
- You can use the && operator to execute a command and, if it is
successful, execute the next command in the list. For example:
cmd1 && cmd2
- The first command, cmd1, is executed and its exit status
- examined. Only if cmd1 succeeds is cmd2 executed.
- This is shorthand for:
if cmd1 then cmd2 fi
SLIDE 21 CS3411 Shell Scripts 21
- To check for a Unix domain socket in the current working
directory (a socket in the Unix domain, unlike the IPv4 domain, shows up as a directory entry):
% cat checkforsocket.sh #!/bin/sh # usage: checkforsocket.sh { ls -l | grep -s \^s > /dev/null ; } && echo found a socket % ./checkforsocket.sh % cd .. % ls -l SOCKET_0 srwxrwxrwx 1 kearns wheel 0 Apr 2 06:00 SOCKET_0 % ~/courses.d/315/checkforsocket.sh found a socket
SLIDE 22 CS3411 Shell Scripts 22
The | |Operator
| |operator to execute a command and, if it fails, execute the next command in the command list.
cmd1 || cmd2
cmd1 is executed and its exit status examined. If cmd1 fails then cmd2 is executed.
cmd1 if test $? -ne 0 then cmd2 fi
SLIDE 23 CS3411 Shell Scripts 23
- To send a message to a user using the appropriate utility:
% cat writemail.sh #!/bin/sh # usage: writemail.sh user message echo "$2" |{ write "$1" || mail "$1" ;} % ./writemail.sh jmayo hi write: jmayo logged in more than once ... writing to console
hi % ./writemail.sh root hi write: root not logged in
From: Jean Mayo <jmayo@mtu.edu> Date: Wed, 3 Apr 1996 17:25:05 -0500 (EST) To: root@mtu.edu hi
SLIDE 24 CS3411 Shell Scripts 24
The test Command
- The shell uses a command called test to evaluate conditional
- expressions. Full details of this command can be found in the
t es t (1 )manual page.
% cat testfile.sh if test ! -f $1 then if test "$WARN" = "yes" then echo "$FILE does not exist" fi fi % ./testfile.sh fubar % ( setenv WARN yes ; ./testfile.sh fubar ) fubar does not exist
SLIDE 25
CS3411 Shell Scripts 25
The tes tcommand can also do numeric tests:
% cat testargs.sh #!/bin/sh # usage: testargs.sh arg1 arg2 ... if test $# -gt 2 then echo "more than 2 args" else echo "less than or equal to 2 args" fi % ./testargs.sh less than or equal to 2 args % ./testargs.sh a less than or equal to 2 args % ./testargs.sh a b less than or equal to 2 args % ./testargs.sh a b c more than 2 args % ./testargs.sh "a b c" less than or equal to 2 args
SLIDE 26 CS3411 Shell Scripts 26
- Commonly-used alternative syntax for
t es t, but with exactly the same semantics:
% cat testargs.sh #!/bin/sh # usage: testargs.sh arg1 arg2 ... if [ $# -gt 2 ] then echo "more than 2 args" else echo "less than or equal to 2 args" fi