Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

Matter by wpr1947

VIEWS: 4 PAGES: 99

									                Advanced UNIX (BASH)




   Objectives
     explain how to write Bourne and Bash
      Shell scripts
Overview
1.   Making a File Executable
2.   Combining Commands
3.   Redirecting Output
4.   Executing Scripts
5.   Variables
6.   Control Flow



                      continued
7.    Functions
8.    Other Commands
9.    Here Documents
10.   Debugging
11.   More Information
1. Making a File Executable
       $ cat whoson
        date
        echo Users currently logged on
        who


       Wrong:
          $ whoson
          whoson: Permission denied
                 Right:
   $ ls -lg whoson
    -rw-r--r-- 1 ad pubs 42 Jun 17 10:55 whoson
    $ chmod u+x whoson
    $ ls -lg whoson
    -rwxr--r-- 1 ad pubs 42 Jun 17 10:55 whoson

   $ whoson
    Tue Nov 7 13:21:34 ICT 2000
    Users currently logged in
    ad    consol Nov 7 08:26
    jenny tty02 Nov 7 10:04
         Possible PATH Problem
   $ whoson
    whoson: Command not found


   Due to PATH shell variable (see later)

   Quick fixes:
              $ ./whoson
       or     $ sh whoson
2. Combining Commands
      Sequencing:
                  $ a ; b ; c

      same as:
                  $ a
                  $ b
                  $ c
    Process Creation (&)
   $ a & b & c
    14271           (PID for a)
    14272           (PID for b)

   $ a & b & c &
    14290
    14291
    14292
    $

   $ a | b | c &
    14302           (PID for piped commands)
                Processes in Action
    $ cat a
    echo -n   “aaaaaaaaaaaaaaaaaaaaa”
    echo -n   “aaaaaaaaaaaaaaaaaaaaa”
    sleep 2
    echo -n   “aaaaaaaaaaaaaaaaaaaaa”
    echo -n   “aaaaaaaaaaaaaaaaaaaaa”


   Similarly for b and c               On the lab
                                        machines there
   Try the following a few times:      isn't much
      $ a & b & c &                     variation unless
                                        the machine is
                                        loaded.
3. Redirecting Output
   1>       redirect standard output (stdout)
    2>       redirect standard error (stderr)

    $ cat a b 1> out 2> err


                                               Files
                                    stdout out

                          cat a b
                                      stderr      err
>&
   redirect one stream into another:
     2>&1              redirect stderr into
      stdout

    $ cat a b 1> theLot 2>&1

                   stdout     theLot

         cat a b
                     stderr
               4. Executing Scripts
   Make sure that a script is executed by the
    Bourne Shell:
      $ sh whoson        (no need for chmod)

   or:
      $ cat boss
      #!/bin/sh
      echo Definitely Bourne Shell Script



                                        continued
   On Linux machines (e.g. calvin), the Bourne
    shell has been replaced by Bash
       sh   means the Bash shell
 5. Variables
5.1. User-defined Variables

5.2. Environment Variables

5.3. Readonly Shell Variables
5.1. User-defined Variables
      $ person=alex
                            No spaces
       $ echo person        around the =
       person
       $ echo $person
       alex


      $var   returns the value stored in var
        called   substitution
5.1.1. Switch off
Substitution
       Swich off substitution with 'var' or
        \var

       $ echo '$person'
        $person
        $ echo \$person
        $person
      5.1.2. Switch off Special Chars (")
   "" switches off the special meaning of characters
    used in filename generation (e.g. *, ?)

   $ ls            // directory contents
    ad.report
    ad.summary
   $ memo=ad*
    $ echo "$memo"
    ad*                          * means only *
    $ echo $memo
    ad.report ad.summary
                                  * means any number
                                  of characters
5.1.3. Exporting Variables
   Normally a variable is local to the running
    script (the process).

   It is sometimes useful if running scripts
    (processes) can access another script‟s
    variables.

   e.g.                                        we want to
                            calls               use cheese
                 extest             subtest
                                                in subtest
           cheese=english
No Exporting: extest1 &
subtest
   $ cat extest1           Using " is
    cheese=english          a good habit,
    echo "extest1 1: $cheese" later
                            see
    subtest
    echo "extest1 2: $cheese"

    $cat subtest
    echo "subtest 1: $cheese"
    cheese=swiss
    echo "subtest 2: $cheese"




                                continued
   $ extest1              subtest does not
    extest1 1: english     see extest1's
    subtest 1:             cheese value
    subtest 2: swiss
    extest1 2: english



               extest1 is not affected
               by subtest's setting of
               cheese
Exporting: extest2 & subtest
   $ cat extest2
    export cheese
    cheese=english
    echo “extest2 1: $cheese”
    subtest
    echo “extest2 2: $cheese”

   $ extest2
    extest2 1: english
    subtest 1: english
    subtest 2: swiss            cheese value passed in
    extest2 2: english
                                change not exported
                                from subtest
                  5.1.4. Reading
   $ cat readln                    read inputs everything
    echo -n “Type: ”                up to the newline
    read ln
    echo “You entered: $ln”

   $ readln
    Type: The Wizard of Oz
    You entered: The Wizard of Oz
No Quotes
   $ cat readlnnq
    echo -n “Type: ”
    read ln
    echo You entered: $ln

   $ ls
    ad.report summary1    directory
    $ readlnnq            contents
    Type: *
    You entered: ad.report summary1
5.1.5. Executing Commands
                         A very simple shell
      $ cat proc_cmd
       echo -n “Enter a command: ”
       read command
       $command
       echo Thanks

      $ proc_cmd
       Enter a command: echo Display this
       Display this
       Thanks
              5.1.6. Splitting Input
                                         Text is split
   $ cat split3                         based on white
    echo -n “Enter something: ”          space.
    read word1 word2 word3
    echo “Word 1 is: $word1”
    echo “Word 2 is: $word2”
    echo “Word 3 is: $word3”

   $ split3
    Enter something: this is something
    Word1 is: this
    Word2 is: is
    Word3 is: something
   $ split3
    Enter something: this is something else, x
    Word1 is: this
    Word2 is: is
    Word3 is: something else, x




                             The last variable gets
                             everything that is left
                             in the input.
               5.1.7. Command
               Subsitution
                                            Must use ‘
   $ cat mydir
    this_dir=„pwd„
    echo “Using the $this_dir directory.”
    this_date=$(date)
    echo "Today's date: $this_date"
                                               A Bash
                                               addition
   $ mydir
    Using /home/ad/teach/adv-unix/bourne directory
    Today's date: Tue Nov 7 13:52:46 ICT 2000
    $
    5.2. Environment Variables
   Most environment variables get their values from
    the shell at login.

   The values of some of the variables can be set
    by editing the .profile file in your home directory
     Bash   uses .bash_profile and .bashrc
5.2.1. Examples
   HOME              pathname of your
    home directory

   $ pwd
    /home/ad/planning
    $ echo $HOME
    /home/ad         cd uses HOME
    $ cd
                     to return to your
    $ pwd
    /home/ad         home directory



                                 continued
   PATH
                where executable can be found
     directories
     represented as a string of pathnames separated by
      „:‟s

   $ echo $PATH                             Extend the
    /usr/local/bin:/usr/bin:/bin:
                                             default PATH
    $ PATH=SPATH":/home/ad/bin:."
    $ echo $PATH
    /usr/local/bin:/usr/bin:/bin:/home/ad/bin:.
Note for SysAdmins
   If you are the system administrator
    (superuser, root) for your machine,
    do not extend your path with "."
     itopens you to potential attack by
      hackers
     e.g. 'fake' UNIX utilities placed in
      the current directory
               5.2.2. Typical .profile
   $ cat .profile
    TERM=vt100
    PATH=$PATH":/home/ad/bin:."
    PS1=“ad: “
    CDPATH=:$HOME
    export TERM PATH PS1 CDPATH

    stty kill ^u

   $ . .profile
                                  export needed
                                  in the Bourne
                                  shell
    5.2.3. Typical .bash_profile
   On calvin, .bash_profile simply invokes your
    .bashrc (if it exists):

      umask 002
      if [ -f ~/.bashrc -a PS1="\$ " ]; then
         . ~/.bashrc
      fi



                     These shell commands
                     will be explained later
                                               continued
Typical .bashrc
   PS1="\u@\h$ "
    # PS1="\w[\#]$ "    No export needed
    PATH=$PATH":."

    alias ls='/bin/ls -F'
    alias dir='ls -ba'
    alias cls="clear"
        :                   These features
        :
                            will be explained
    psgrep()                later.
    {
      ps aux | grep $1 | grep -v grep
    }
               5.2.4. set
   The current settings for the environment
    variables can be listed with set:

      $ set | more
      BASH=/bin/bash
             :
      PATH=/usr/local/bin:/usr/bin:/bin:.
             :
      PS1='\u@\h$ '
             :
5.3. Readonly Shell Variables
           These are environment
            variables that cannot have their
            values changed.

           Most of them relate to the
            arguments supplied to a script
            when it is called.
5.3.1. Script Name ($0)
   $ cat abc
    echo The name of this script is $0

   $ abc
    The name of this script is abc
5.3.2. Script Arguments ($1, $2,..., $9)

              $ cat display_5args
               echo The first five command line
               echo arguments are $1 $2 $3 $4 $5


              $ display_5args jenny alex helen
               The first five command line
               arguments are jenny alex helen




                          If the variable has no value,
                          then nothing is printed.
              5.3.3. All Arguments
              ($*)
   $ cat display_all
    echo $*

   $ display_all a b c de fg hi jk mno pqr
                                stu w x y z
    a b c de fg hi jk mno pqr stu w x y z



   $@ is like $* but puts “...” around each printed
    argument
5.3.4. Number of Arguments
($#)
          $ cat num_args
           echo “This script has $# arguments.”

          num_args helen alex jenny
           This script has 3 arguments
5.3.5. The shift Commnd

         shift moves argument values on
          the command line one $<number>
          to the left.

         Overcomes limit of 9 argument
          variables
          ($1, $2, ..., $9)


                                 continued
   $ cat demo_shift
    echo “arg1= $1 arg2= $2 arg3= $3”
    shift
    echo “arg1= $1 arg2= $2 arg3= $3”
    shift
    echo “arg1= $1 arg2= $2 arg3= $3”
    shift

   $ demo_shift   alice   helen jenny june
    arg1= alice    arg2=   helen arg3= jenny
    arg1= helen    arg2=   jenny arg3= june
    arg1= jenny    arg2=   june arg3=




                              jenny "moves"
                              to the left.
5.3.6. The set Command
(Again)
         set „cmd„                  (must
          use „)

           evaluates  cmd and assigns its
            values to the script command line
            arguments ($1, $2, ..., $9, $*)
           the values in cmd output are
            separated by whitespace

                                   continued
   $ date
    Fri Jun 17 23:04:09 GMT+7 1996
    $ cat dateset
    set „date„
    echo $*
    echo                             The date values
    echo “Argument 1: $1”            are assigned to $1,
    echo “Argument 2: $2”            $2, etc.
    echo “Argument 3: $3”
    echo $2 $3, $6




                                             continued
   $ dataset
    Fri Jun 17 23:04:13 GMT+7 1996

    Argument 1: Fri
    Argument 2: Jun
    Argument 3: 17
    Jun 17, 1996
6. Command Flow
 6.1.   Branching
 6.2.   Test Forms
 6.3.   Looping
 6.4.   break, continue, :
 6.5.   trap
6.1. Branching
   $ cat same_word
    echo -n “word 1: ”   Use " to stop
    read word1           filename
    echo -n “word 2: ”   expansion
    read word2
    if test "$word1" = "$word2"
    then
      echo Match
    fi
    echo End of Program




                                continued
   $ same_word
    word1: peach
    word2: peach
    Match
    End of Program
               6.1.1. Second Format
                              Redirect
   $ cat chkargs
                                         stdout to stderr
    if [ $# = 0 ]
    then
      echo Usage: chkargs argument... 1>&2
      exit 1
    fi
    echo Program running
    exit 0

   $ chkargs
    Usage: chkargs argument...
    $ chkargs abc
    Program running
6.1.2. if-then-else              C programmers
                                 prefer this format
   $ cat show
    if [ $# = 0 ]; then
      echo Usage: show [-v] filenames 1>&2
      exit 1
    fi
    if [ “$1” != “-v” ]
    then
      cat “$@”
    else
      shift
      more “$@”
    fi



                       Use:
                        $ show -v f1.txt f2.txt
6.1.3. if-then-elif             For multiway branches


   $ cat same3
    echo -n “word   1: ”
    read word1
    echo -n “word   2: ”                -a means "and"
    read word2                          \ means "continued
    echo -n “word   3: ”                on next line"
    read word3
    if [ “$word1”   = “$word2” -a \
                      “$word2” = “$word3” ]
    then
      echo “Match: words 1, 2, and 3”




                                                continued
elif [   “$word1” = “$word2” ]
then
  echo   “Match: words 1 and 2”
elif [   “$word1” = “$word3” ]
then
  echo   “Match: words 1 and 3”
elif [   “$word2” = “$word3” ]
then
  echo   “Match: words 2 and 3”
else
  echo   “No match”
fi
6.1.4. case                       Better style: specify
                                  the shell, and comment
                                  the code.
   $cat command_menu
    #!/bin/sh
    # menu interface to simple commands

    echo   “\n COMMAND MENU\n”
    echo   “ a. Current date and time”
    echo   “ b. Users currently logged in”
    echo   “ c. Name of working directory”
    echo   “ d. Contents of working directory”
    echo   -n “Enter a, b, c, or d: ”
    read   answer
    echo




                                               continued
case “$answer” in
  a) date
        ;;
  b) who
        ;;
  c) pwd
        ;;
  d) ls -C                      * is the default;
        ;;                      always include it
  *) echo “$answer not legal”   at the end
    ;;
esac
echo
   $ command_menu
             COMMAND MENU

     a. Current date and time
     b. Users currently logged in
     c. Name of working directory
     d. Contents of working directory
    Enter a, b, c, or d: a

    Fri Jun 17 14:11:57 GMT 1996
               Other case Patterns
   ?         matches a single character

   [...] any character in the brackets.
               Use - to specify a range (e.g. a-z)

   |         or (e.g. a|A)

   *         it can be used to match "any
              number of characters"
   $cat timeDay
    #!/bin/sh
    echo Is it morning? Answer yes or no
    read timeofday

    case "$timeofday" in
      "yes" | "y" | "Yes" | "YES" )
         echo "Good Morning"
          ;;
      [nN]* )
         echo "Good Afternoon"
         ;;
      *) echo "Uhh??"
         ;;
    esac
6.2. test Forms
    Used in the conditions of if's and loops.

   Format:
       test expr
       [ expr ]
   e.g.
       test “$word1” = “$word2”
       [ “$1” != “-v” ]
       [ “$word2” = “$word3” ]
       [ “$word1” = “$word2” -a \
                   “$word2” = “$word3”
       ]
6.2.1. String
Expressions
   string1 = string2

   string1 != string2


   -n string       (true if string is not ““)

   -z string       (true if string is ““)
6.2.2. Numerical
Expressions
   number1 -eq number2   (equality)
   number1 -ne number2
       (inequality)

   number1 -lt number2   (<)
   number1 -le number2   (<=)

   number1 -gt number2   (>)
   number1 -ge number2   (>=)
              6.2.4. File Test
              Expressions
   -f file         (file exists)
   -d file         (file exists but is a directory)

   -r file         (file is readable)
   -w file         (file is writable)
   -x file         (file is executable)
6.2.5. Combining
Expressions
   ! expr                               (not expr)

   expr1 -a expr2               (and)
       Bash allows   && as well

   expr1 -o expr2               (or)
       Bash allows || as well

   ( expr )
6.3. Looping (for-in)
   Format:

      for loop-index in argument-
      list
      do
         commands
      done
   $ cat fruit
    for fruit in apples oranges pears
    do
      echo $fruit
    done
    echo Task completed

   $ fruit
    apples
    oranges
    pears
    Task completed
Looking for “for” in files
   First version of script:

    $ cat file-fors1
      for f in „ls„
      do
         echo $f
      done
   $ cat file-fors2
    for f in „ls„        Ignore output
    do
      grep -i “for” $f > /dev/null
      if [ $? == 0 ]
      then
        echo $f
      fi
    done
6.3.1. for
   $ cat whos
    # Give user details from /etc/passwd
    if [ $# = 0 ]
    then
      echo Usage: whos id... 1>&2
      exit 1
    fi

    for i           # read as for i in “$@”
    do
      awk -F: ‟{print $1, $5}‟ /etc/passwd |
                            grep -i “$i”
    done                                     awk variables
                                             with ‟
                 6.3.2. while
   $ cat count
    number=0
    while [ $number -lt 10 ]
    do
      echo -n "$number"
      number=„expr $number + 1„
    done
    echo

   $ count
    0123456789
    $
Watching for Mary to log in
       while sleep 60
        do
          who | grep mary
        done


       Disadvantages:
         ifMary is already logged in, then
          we must
          wait 60 secs to find out
         we keep being told that Mary is
          logged in
              6.3.3. until
   Format:
      until command
      do
         loop body until
         the command evaluates to true
      done
   Watching (v.2):
      until who | grep mary
      do
         sleep 60
                                  loop until grep
      done
                                  returns ‘true’ (0)
6.3.4. Extending
Watching
   Generalise so can watch for
    anyone:
       $ watchfor ad


   Watch for everyone logging in/out:
       $ watchwho
watchfor
 #!/bin/sh
 # watchfor
 # watch for person supplied as argument

 if [ $# = 0 ]
 then
   echo “Usage: watchfor person”
   exit 1
 fi
 until who | grep “$1”
 do
   sleep 60
 done
                watchwho
   Once a minute, run who and compare its
    output to that from a minute ago. Report any
    differences.

   Keep the who output in files in /tmp

   Give the files unique names by adding the
    shell variable $$.
     $$   is the PID of the user‟s shell
#!/bin/sh
# watchwho: watch who logs in and out

new=/tmp/wwho1.$$
old=/tmp/wwho2.$$
> $old      # create an empty file

while true
do
  who > $new                        An advanced
  diff $old $new                    Shell programming
  mv $new $old
  sleep 60
                                    technique: |
done | awk ‟/>/ {$1 = “in: “; print}
             /</ {$1 = “out: “; print}‟
                Use
   $ watchwho
                                                      initial
    in: root tty1 Nov 6 09:32                         users
    in: ad pts/3 Nov 8 08:49 (myrrh.coe.psu.ac.th)
    in: s4010441 pts/5 Nov 8 10:11 (192.168.0.134)
    in: ad pts/4 Nov 8 10:12 (myrrh.coe.psu.ac.th)
    in: s4010143 pts/17 Nov 7 23:57 (192.168.0.204)
    out: ad pts/4 Nov 8 10:12 (myrrh.coe.psu.ac.th)
    in: ad pts/4 Nov 8 10:16 (myrrh.coe.psu.ac.th)
    out: ad pts/4 Nov 8 10:18 (myrrh.coe.psu.ac.th)
               :
              Notes
   diff uses „<„ and „>„ to distinguish data from
    $old and $new

   $ diff old new
    < ad
    > mary

                          old           new
                          john          john
                          ad            mary




                                         continued
                                 while      awk
                                 loop

   The output from the while loop is piped into
    awk
     only one call to awk is required
     the "pipe" programming style


   A calvin problem:
         had to be called with the -W interactive
        awk
      option so that its output was not buffered
     otherwise nothing would appear
6.3.5. Checking mail
   Have a script watch your mailbox
    periodically, and report whenever
    the mailbox changes by printing
    “You have mail”.


   Usage:
     $ checkmail        # checks every 60
      secs
     $ checkmail 120          # checks
      every 120 secs
               checkmail
#!/bin/sh
# checkmail: watch mailbox for growth

time=${1-60}

oldls="„ls -l $MAIL„"
while true
do
  newls="„ls -l $MAIL„"
  echo $oldls $newls
  oldls="$newls"
  sleep $time
done | awk ‟$5 < $14 {print “You have mail”}‟




                 uses the pipe technique
Notes
   $MAIL is a builtin shell variable, with
    the value   /var/spool/mail/$USER


         sets t to $1 or, if no
    t=${1-60}
    argument is provided, to 60
     General  form: ${var-thing}
      returns value of var if defined;
      otherwise thing


                              continued
   Use awk to print a message only when the
    mailbox gets bigger:
       awk $5 $14 compares the size fields of the two ls -l
        calls output at the end of each iteration

    e.g.
      $ ls -l foo                    5th value
      -rw-r--r-- 1 ad ad 34512 Nov 13 1996 foo
      $ ls -l foo
      -rw-r--r-- 1 ad ad 34512 Nov 13 1996 foo



                                          14th value
                  6.4. break, continue, :
   break   and   continue   are used as in C:
       break   escapes from a loop

        for file in fred*
        do
          if [ -d "$file" ]; then      # deleted?
            break                 # finish loop
          fi
             # do something
             #
        done


                                             continued
   continue   goes to the top of a loop:
      for file in fred*
      do
        if [ -d "$file" ]; then     # deleted?
          continue         # go back to loop top
        fi
           # do something
           #
      done

                                            continued
   The ':' command is the same as
    true, but runs a tiny bit faster
     often   used to simplify control logic
      if [ -f fred ]; then        # is fred
      a file?
        :     # do nothing
      else
        # do something
        #
      fi
                  6.5. trap
   Capture user interrupts or system call failures.

   Format (with ‟):
      trap ‟commands‟ signal-numbers-or-name


   Some signal numbers (names):
     2 (INT)          press delete or control-C
     3 (QUIT)         press control-| or control-\
     15 (TERM)        kill command signal

                                                 continued
   A complete list of available signals is given
    by typing trap -l at the command line.

   To ignore a signal, set the   trap   command
    to be empty ( ‟‟)

   To reset signal processing, set the
    command to -



                                           continued
   $ cat inter
    trap ‟echo PROGRAM INTERRUPTED; exit 1‟   INT
    while true
    do
      echo Program running.
      sleep 2
    done
7. Functions
   Bash allows shell scripts to use
    functions:
      function_name() {
        statements
      }


   Functions must be defined
    textually before they are used.


                            continued
   Functions can   return   integer values

   Function parameters are passed by modifying
    $*, $@, $#, $1 -- $9 while the function is
    executing.

   Local variables are defined with the      local
    keyword
     the other variables in a script are global by
      default
                my_name
   #!/bin/sh

    yes_or_no() {                    # a function
      echo "Is your name $* ?"
      while true
      do
         echo -n "Enter yes or no: "
         read x
         case "$x" in
           y | yes ) return 0;;
           n | no ) return 1;;
           * )        echo "Answer yes or no"
         esac
      done
    } # end of yes_or_no()



                                               continued
# the main part of the script

echo "Original parameters are $*"

if yes_or_no "$1"
then
  echo "Hi $1, nice name"
else
  echo "Never mind"
fi

exit 0
Use
   $ my_name andrew davison
    Original parameters are andrew davison
    Is your name andrew ?
    Enter yes or no: y
    Hi andrew, nice name
    $
              8. Useful Scripting
              Commands
   expr evaluates its argument as an
    expression:
      ans=„expr $x + 1„


   The usually operators are available:
    +    - * / (integer divison) % (modulo)
     > >= < <=
     = (equality) !=
     | (or) & (and)

                                           continued
                  printf
   Bash supports    printf,   as a more flexible   echo
       printf "format string" parameter1 ...


   Very similar to printf() in C
     main  restriction is no support for floats
     only integers are supported in the shell

   $ printf "%s %d\t%s\n" "hi there" 15 students
    hi there 15 students
    $
9. Here Documents
   A here document allows input to be
    passed into a command from
    within a script
     the  command thinks the input is
        coming from a file or input stream

   A here document begins with
    <<LABEL, and ends with LABEL
       LABEL   can be anything
   $ cat here1
    #!/bin/sh

    cat <<!FUNKY!
    hello
    this is a here   the here
    document         document
    !FUNKY!

   $ here1
    hello
    this is a here
    document
    $
10. Debugging
   Various options can be set when
    invoking a shell script to help with
    debugging.

   There are two ways to set the
    options:
     from  the command line when
      calling the script
     from within the script by using set

                             continued
Command Line                Set
   sh -n script            set -n
     do   not execute the script, only parse it

   sh -v script            set -v
     echoes    commands after executing them

   sh -x script            set -u
     warns   when an undefined variable is used
11. More Information
   The Bourne Shell:
     Ch.   10, Sobell

   Bourne/Bash:
     Beginning Linux Programming
      Neil Matthew and Rick Stones
      Chapter 2

								
To top