Other Shell Features

What other things can enhance my scripts

Daemonizing

Sometimes you want a script to run as a daemon, in the background and never ending. To do this properly you need to be able to detach your script from its controlling TTY—that is, from the terminal session used to start the daemon.

  • Use nohup.
    • nohup foo.sh &
    • Should also redirect stdout.
  • Apparently on xenial my shell was set to not send the HUP signal when closing the tty shopt | grep huponexit
    • You can change this behavior with shopt -u huponexit; shopt | grep huponexit or shopt -s huponexit; shopt | grep huponexit

Reusing codes with includes and sourcing

    # vars.sh 
    name='joe'
    age=22
    color='red'

    #script.sh
    source vars.sh
    printf "My name is %s\n" $name
    printf "My age is %s\n" $age
    printf "My color is %s\n" $color
  • The word source can be replaced with ..
  • One of the best uses of sourcing scripts comes when you define bash functions

Defining Functions

  • function definitions should go at the top of your shell script, or at least somewhere before you need to invoke the function.
  • when you may need to re-use some commands

Function example

    #!/bin/bash
    function usage ()
    {
        printf "usage: %s [ -a | - b ] file1 ... filen\n " $( basename $0 )
    }
    
    
    if [ $# -lt 1 ]
    then
        usage
    fi

Sending values to functions

    function add ()
    {
       z=$(( $1 + $2 ))
       printf "z is %s" $z
    }
    
    add 8 12 
  • You don’t put parentheses around the arguments like you might expect from some programming languages. Put any parameters for a bash function right after the function’s name, separated by whitespace, just as if you were invoking any shell script or command.

Returning values from a function

  • You have two ways to get values back from a function. First, you can assign values to variables inside the body of your function. Those variables will be global to the whole script unless they are explicitly declared local within the function.

      function sample ()
      {
              msg=$1' is my friend'
      }
      
      sample "Tom"
      printf "%s" $msg
    

Returning values from a function

  • Can also return using the echo or printf statement.

      function sample ()
      {
              echo $1' is my friend'
      }
      
      t=$(sample "Tom")
      echo $t
    

Other function stuff

  • Within the function, the parameters are referred to as if they were command-line arguments by using $1, $2, etc. However, $0 is left alone. It remains the name by which the entire script was invoked. On return from the function, $1, $2, etc. are back to referring to the parameters with which the script was invoked.
  • Also of interest is the $FUNCNAME array. $FUNCNAME all by itself references the zeroth element of the array, which is the name of the currently executing function. In other words, $FUNCNAME is to a function as $0 is to a script, except without all the path information.

FUNCNAME

    function sample ()
    {
            echo "We are in $FUNCNAME"
    }
    
    sample

Redefining commands with alias

  • You have already done this
  • alias ls='ls -a'

Counting elapsed time

  • use time builtin
  • or $SECONDS
    • "[$SECONDS] expands to the number of seconds since the shell was started. Assignment to this variable resets the count to the value assigned, and the expanded value becomes the value assigned plus the number of seconds since the assignment."

Examples

    #seconds
    started="$SECONDS"
    sleep 4
    echo "Run-time = $(($SECONDS - $started)) seconds..."
    
    bash seconds
    time bash seconds

Time

Real is wall clock time - time from start to finish of the call. This is all elapsed time including time slices used by other processes and time the process spends blocked (for example if it is waiting for I/O to complete).

User is the amount of CPU time spent in user-mode code (outside the kernel) within the process. This is only actual CPU time used in executing the process. Other processes and time the process spends blocked do not count towards this figure.

Sys is the amount of CPU time spent in the kernel within the process. This means executing CPU time spent in system calls within the kernel, as opposed to library code, which is still running in user-space. Like 'user', this is only CPU time used by the process.