Shell Scripting Tips (revisited)

Nick Holland

Target Audience

Keep it neat and simple

Classes of scripts

Deal with errors

-e : Trap all errors!

#!/bin/ksh -e

cd /some/dir
rm -r *   # Could be bad if the 'cd' failed!
  • Big hammer. Often too big.
  • Header for Q&D scripts?

    #!/bin/ksh
    yell() { echo "$0: $*" >&2; }
    die()  { yell "$*" ; exit 111; }
    try()  { "$@" || die "cannot $*"; }
    
    try cd /some/dir
    rm -r *   # Could be bad if the 'cd' failed!
    
     
    $ ./test.ksh   
    ./test.ksh[7]: cd: /some/dir - No such file or directory
    ./test.ksh: cannot cd /some/dir
    
  • A more selective hammer, but still...a hammer
  • but possibly what you need for Q&D.
  • Validate all input

  • Don't try to remove undesired things. Only accept things you expect.
  • "tr" is your friend -- "-d" (delete) and "-c" (complement).
  • tr -dc "valid-characters"
  • INPUT=$(echo "$INPUT"|tr -dc "a-zA-Z_0-9-")
  • definitely good for user-facing code
  • Make friends with set, typeset

    set -f -- Turn off globbing!

    $ A="*"
    $ echo $A
    Desktop Downloads ShellScriptTips.odp ShellScriptTips01.odp
       [...]
    $ set -f  
    $ A="*"
    $ echo $A
    *
    $ 
    
  • don't forget if you are turning globbing off!
  • set -- $V -- put $V into $*

    $ A="     A    b  c D   e    "
    $ echo "$A"
         A    b  c D   e    
    $ echo "$*"
    
    $ set -- $A
    $ echo "$*" 
    A b c D e
    $ echo "$3"
    c
    

    Case insentitivity: tr(1)

    $ V="AbCdEf"
    $ V=$(echo $V | tr "A-Z" "a-z")
    $ echo $V
    abcdef
    $ 
    

    Case insentitivity: the lazy way

    $ typeset -l V
    $ V="AbCdEf" ; echo $V
    abcdef
    $ typeset -u V         
    $ V="AbCdEf" ; echo $V 
    ABCDEF
    

    tput(1)

    BOLD=$(tput bold)
    NORM=$(tput sgr0)
    print -n "Enter your input ->$BOLD"
    read response
    print -n "$NORM"
    
    Lots of other options, varying degrees of portability, however.

    General Tips(using KSH!)

    From Robert Peichaer (rpe@openbsd)

    Commonly forgotten tools

    print vs. echo

  • echo : display string with newline
    • no options! (originally)
    • Ambiguities in the POSIX standard
  • print : better display string with newline
    • Better definition in POSIX
    • not in bash :-/
  • Nick's suggestion: IF both are available, use print
    • ...but echo makes a great debugging tool.
    • when program works, search for "echo", remove.
  • "Here documents"

    Much less picky about formatting characters than many other ways to store data.
    ## Classic:
    cat <<__ENDOFTEXT
    this text is to be output.
    __ENDOFTEXT
    
  • really messes with indentation
    # Starting your "here doc" with "<<-" will 
    # strip off leading tab characters. 
        cat <<-__ENDOFTEXT
    	this is text to be output.
    	__ENDOFTEXT
    
    
  • Running as root (or anyone)

    # Check to see who we are running as, if not
    #   root, re-invoke with sudo.
    if [[ $(whoami) != "root ]]; then
        if ! sudo -n -u root $0 $* 2>/dev/null; then
            echo "Sorry, sudo isn't configured properly
            logger "$0 sudo is broke"
            sleep 2
        fi # sudo failed
        exit 
    fi # not yet root
    # We are now running as root
    
  • Hopefully, $0 returns 0.
  • Reporting Tips

    Remote administration with SSH

    Optimizing admin with SSH

    Auto-change control

    ksh "select"

    $ PS3="Pick a motorcycle ->"          
    $ select MOTORCYCLE in K100 K1200LT Buell Harley; do
    > print "Riding the $MOTORCYCLE today"
    > done
    1) K100
    2) K1200LT
    3) Buell
    4) Harley
    Pick a motorcycle ->2
    Riding the K1200LT today
    Pick a motorcycle ->^C
    
    In modern bash now

    Prompt maddness

  • Traditional Unix Prompt: "#" or "$" (or "%")
  • More info:
    • /usr/src $
    • nick@fluffy3 /usr/src/sys/arch/amd64/compile/GENERIC.MP $
  • Crazy info
    • date time PWD user, machine+domain name, shell name and version, history number ...
  • Prompt maddness

    Shell Scripting Tips

  • Discussion? `
  • /