Home Menu

Shell Programming


Contents

Topics

Assignment



Shell Basics

A shell refers to the command interpreter that provides the working environment on a Unix or Linux host. The shell can be used to execute commands directly, or to write scripts.

We are going to discuss Shell programming, where Shell refers specifically to the Bourne Shell. The Bourne Shell capabilities are included in several variants including sh, bash, bsh, ksh and pdksh. The other shell schemes are based on the C-shell, which is less capable and more difficult to write scripts with.

Running Shell Programs

Definitions

Bash, like most shells, has a number of control characters that have special meaning.

Metacharacters, when unquoted, separate words. They are

Escaping, allows metacharacters to have their normal meaning. For example,

Control operators perform some function. They are:

Reserved words are words that have special meaning and cannot be used for user defined names:

    ! case do done elif
    else fi for function if
    in select then until { }

Bash Environment Variables

There are also a large number of predefined environment variables. Some of the more important are:

    HOME Your home directory
    HOSTTYPE Returns the hosttype
    IFSThe current separator used for word splitting
    LINENO Generates the current line in the script
    MAILMail spool path
    OSTYPE Returns the operating system
    PATHSearch path for executables
    PS1Login prompt
    PWDCurrent directory
    RANDOMGenerates a random number when properly set
    SHELLCurrent shell
    USERYour user name



Shell Variables

Working With Shell Variables

  • variable=value     -   set the value of a variable
  • No spaces around the "="

    • CLASSPATH="/usr/java/jre/lib"
    • PATH="/usr/bin:/usr/local/bin:/bin:/sbin:"
    • COUNT=10

  • export variable     -   make a variable globally accessible to other processes

    • export CLASSPATH

  • $variable     -   access the value of a variable

    • $count=$count+1
    • ls $dir

  • echo [options] args     -   output the value of the args

    • echo "The count is" $count     =>     The count is 14

Script Basics

  • #     -   comment remainder of the line
  • The first line specifies the script interpreter
        e.g. #! /bin/sh or #! /bin/bash
  • Arguments - Each argument is numbered from $1 to $N, where there are N arguments. For example,

      mysilly_script myhome 8 bozo

      $1 = "myhome"
      $2 = 8
      $3 = "bozo"

      There are some special symbols

      $@ = A list of all arguments, as quoted strings
      $# = The number of arguments
      $* = A list of all command line arguments.

Expansion

After a shell command is split into words, there are 7 levels of expansion performed in the following order

    brace
    tilde
    variable and parameter
    command substitution
    arithmetic
    word splitting
    pathname

Each of these provides particular properties as described briefly below. This is a very large topic and to get complete understanding you need to know more about the scripting lanaguage, so use the following as an introduction and reference. Just remember that all of these expansions are going on.

    brace expansion

      Generate arbitrary strings.

        ls /usr/{src,lib,share} = ls /usr/src; ls /usr/lib; ls/usr/share

        chmod 644 /home/bozo/{public,d?t?.*} = chmod 644 /home/bozo/public;
            chmod 644 /home/bozo/d?t?.*

    tilde expansion

      If a word begins with a tilde ("~"), all characters preceding the first slash ("/") are treated as a possible login name. If the possible login name is null, it is replaced with the value of the HOME environment variable, or if unset, the home directory name of the user. If tilde is followed by +, then PWD is used and if followed by a -, the OLDPWD is used. This expansion is also executed on unquoted instances of : and =.

        ls ~bozo = ls $HOME/bozo
        ls ~zippo/net = ls /home/zippo/net
        ~+/files/prog= $PWD/files/prog
        PATH=$PATH:~/bin = PATH=$PATH:$HOME/bin

variable and parameter expansion

    A dollar sign ("$") introduces parameter, command and arithmetic expansion. The name following the $ is expanded. The name may be included in braces, mostly to protect it from following expansions. Braces are required if the name is a positional parameter with more than one digit.

      DIR="x y z"    
      ls $DIR = ls x y z
           
      CMD="ls"   
      USER="bob"   
      DIR="files"   
      assume ${13}= abc
      $CMD /home/${USER}$DIR ${13}= ls /home/bob/files/abc

There are quite a group of special cases. In the following, if parameter is set, it is used. If not word is used in the following way:

${parameter:-word} - use word (Use default values)

    ls ${DIR:-~}
    = ls $DIR or ls ~

${parameter:=word} - assign word (Assign default values)

    ls ${NAME:=Bob}
    = ls ~ set NAME="Bob"

${parameter:?word} - write word to standard error (Display error)

    ls ${DIR:="undefined"}
    = ls $DIR or output "undefined"

${parameter:+word} - substitute word if parameter is set otherwise substitute nothing (Substitute alternate value)

    CCOPTS=${DEBUG:="-g"}
    = CCOPTS="-g" or unset

These are quite usefult in scripts for setting default values and handling undeclared parameters and/or environment variables. However, they are not widely used.

command substitution

    Replace a variable with the output of the command represented by the variable. This the result of placing the command in single left quotes. More on this later.

      CMD=ls
      FILES=`$CMD`
      echo $FILES
      asgn4.txt lunch.txt resume.doc

       

      SHORTHOSTNAME=`hostname | cut -d. -f1`

    arithmetic expansion

      This facility allows arithmetic expressions to be evaluated.

      echo $[3+4]

      LINES=`wc outline.html | cut -c1-10`
      PAGES=$[$LINES/25]

    word splitting substitution

      Any result of parameter expansion, command substitution or arithmetic expansion not in double quotes is split into words using IFS (default = space,tab,newline) as the delimiter.

    pathname expansion

      After splitting, any word containing *, ? or [ is regarded as a pattern and replaced with an alphabetically sorted list of pathnames that match.

      ls *spe*

      cat .?mvp.??? >> mvp.data

      manroff man[158]/patch*

Quoting

Quoting is used to remove the special nature of some characters and words. In addition, the escape character "\" is used to preserve the literal value of a character that can be used literally in the shell, or as a special character. To summarize, there are three types of quoting:

    Double Quotes

    All characters have their literal value preserved, with the exception of $,` and \. $ and ` always retain their special meaning, while \ retains it only when followed by $,`,",\ or newline. A double quote may occur between double quotes if it is escaped.

    Single Forward Quotes (left quotes)

    Synonym for command substitution. The value of the expression is the result of the command execution.

    Single Backward Quotes

    All characters have their literal value preserved. A single quote may not occur between single quotes.

    For example, assume CMD=ls
    echo $CMD ~/xyz ls /home/bozo/xyz
    echo "$CMD ~/xyz" ls ~/xyz
    echo '$CMD ~/xyz' $CMD ~xyz
    echo `$CMD ~/xyz` noses bigfeet baggypants
    echo "\$CMD ~/xyz" $CMD ~/xyz
    echo '\$CMD ~/xyz' \$CMD ~xyz
    echo `$CMD ~/xyz` noses bigfeet baggypants
    echo `$CMD "~/xyz"` No such file or direcory
    echo "$CMD '~/xyz'" ls '~/xyz'
    echo "$CMD '~/xyz'" ls '~/xyz'
    echo "`$CMD` ~/xyz" ls of current directory and execute ~/xyz
    echo "`$CMD ~/xyz`" noses bigfeet baggypants
    echo '$CMD '~/xyz'' ls $CMD ~/xyz


Builtin Commands

Bash or Shell has a long list of builtin commands, some of which you already know. For example, pwd, chdir and so on. All of these commands can be used in a shell script, but there are some others that are useful primarily in programming situations.

Builtin Commands


Useful External Commands

There are, of course, hundreds of Unix/Linux commands that you can use, but there are a few that are quite useful for shell programs.

External Commands


Programming Constructs

Any bash command can be used in a script, but this section will concentrate on programming constructs of various kinds. In general, the format of a script file is freeform, with newlines used to separate executable lines of the script.

Simple Commands

    Simple Examples

     

  • Any Linux command.
  • Any exported shell environment variable or alias

command[(arguments)]

    execute the external or internal command

lists


(list)
    list is executed in a subshell

    (echo `wc *`)

{list;}

    list executed in the current shell
Examples

for

for name [in word] do list ; done
    The list of words following in is expanded creating a list of items. name is set to each in sequence and list is executed. If the in clause in not included, the positional parameters are used by default.

Examples

select

select name [in word] do list ; done
    The list of words following in is expanded creating a list of items. The list is output to stderr and prompt PS3 is output. A line is read from stdin and name is set to each the corresponding value. Then list is executed. This continues until a break or return is executed.
Examples

case

case word in [pattern [| pattern]...] list;;]... esac
    word is expanded and matched against each pattern. When a match is found, the corresponding list is executed. The exit status is zero if no match is found or the status of the last command in list executed.
Examples

if-then-else

if list then list[elif list then list] ... [else list fi
    if list is executed and if the status is zero then list is executed, otherwise elif's are executed similarly in order. If none are executed, the else list is executed.

command1 && command2

    command2 is executed if and only if command1 returns an exit status of zero. This is equivalent to:
               if command1
               then 
                  command2
               endif
               

command1 || command2

    command2 is executed if and only if command1 returns an exit status which is non-zero. This is equivalent to:
               if ! command1
               then 
                  command2
               endif
               
Examples

while,until

while list do list done
until list do list done
    The do list is executed as long as the while list returns a status of zero. The until is the same except that is continues while the status in non-zero.
Examples

functions

[function] name () {list;}
    Defines a function name.
Examples


read name1,name2,... Read consecutive words into variables name1, name2, etc.
readRead the input string into the variable REPLY
read -r name1,name2 read without intepreting backslashes



Assignment

  1. Create a shell script that will find all files in the user home directories that have not been accessed in the last 90 days. This is a great way to control disk space usage if you set it up as a cron job to run once per week and then tell users to archive the files or remove them.
  2. Create a script to find all directories in a subtree and change their permissions to rwxr-xr-x (755) and all regular files to rw-r--r-- (644). Use the find command with the type option and xargs to execute chmod.
  3. Create a script that will build a file named
      /var/local/security/filecheck/xxxxx
    that contains file names, sizes, creation times and access times for files. You should be able to specify a directory and have a file created, where the "xxxxx" above becomes the name of the directory. For example, /var/local/security/filecheck/usr-bin for /usr/bin. A nice modification is to allow directories or individual files to be handled this way.
  4. Using the cksum command, create checksums to be placed in the file instead of the file size.
  5. Create a shell script that will read the file created in the previous questions and then check to insure that the current configuration matches what is stored in the file. Obviously, the use of this script is to make sure that critical files in your system haven't been modified. Set up a script to run regular checks on /sbin, /bin, /usr/bin and /usr/sbin.
  6. Here are some other things you could try if you wanted to:
    • Create a script to check various system performance characteristics and output it to a window on your system on a regular basis.
    • Create a script to clean up a directory tree by removing files that are typically unnecessary, such a executables, .ps files or .o files. Note that this is usually a pretty personal set of files.
    • Write a script to test and determine if there is nefarious activity on a TCP port (netstat will give you the data).
    • Write a script to regularly collect network statitistics and send mail to root if network performance is degrading.
    • Do the same for CPU, memory or disk performance.

Home Menu