the bash – defensive scripting
DESCRIPTION
Fairly basic introduction to some principles and techniques for creating safe, fault-tolerant unix scripts using the Bash environment.TRANSCRIPT
The Bash: Defensive Scripting
The Bash: Defensive Scripting
1
Dienstag, 16. August 11
The Bash: Defensive Scripting
UnixInterfacesRe-useDefensive ProgrammingReadings
2
Dienstag, 16. August 11
The Bash: Defensive Scripting
Unix• Be forgiving in what you accept, but strict in what you emit
• If you must fail, do so early and noisily
• One tool for each task• Human-readable data and protocols• Do the simplest thing that will do
3
Dienstag, 16. August 11
The Bash: Defensive Scripting
Unix: The Unix ToolboxGet familiar with cat, cut, tee, uniq, sort, head, tail, but also grep, sed, diff, find and possibly even awk. They will save you a whole lot of work.For more inspiration: ls /usr/binExtend your Unix Toolbox
4
Dienstag, 16. August 11
The Bash: Defensive Scripting
Interfaces• stdin, stdout, stderr, exit code• Favour plain text• Treat comments as comments• Filter, Source, Sink, Cantrip, Compiler
5
Dienstag, 16. August 11
The Bash: Defensive Scripting
Interfaces: FilterRead from stdin, write to stdoutPerfect for pipesExample: cut
6
Dienstag, 16. August 11
The Bash: Defensive Scripting
Interfaces: SourceRead from file, write to stdoutInterface to outer world, beginning of a pipe sequenceExample: cat
7
Dienstag, 16. August 11
The Bash: Defensive Scripting
Interfaces: SinkRead from stdin, write to fileInterface to outer world, end of a pipe sequenceExample: >
8
Dienstag, 16. August 11
The Bash: Defensive Scripting
Interfaces: CantripDo sth. and return nothing but a status code (or errors)This is super scriptableExample: rm
9
Dienstag, 16. August 11
The Bash: Defensive Scripting
Interfaces: CompilerRead from file, write to another fileExample: tar
10
Dienstag, 16. August 11
The Bash: Defensive Scripting
Re-use• Functions• Wrappers• $() (aka ``)• source (aka ‘.’)
11
Dienstag, 16. August 11
The Bash: Defensive Scripting
Re-use: FunctionsWill behave like a script on its ownfunction log () { echo “$(date) ERR $@” >&2}log “Cannot connect”# Do 4 Aug 2011 10:38:58 CEST ERR Cannot connect
12
Dienstag, 16. August 11
The Bash: Defensive Scripting
Re-use: Wrappers#!/bin/bash# file mcd -- make a dir if# necessary and cd to ittest -n “$1” || exit 1newdir=”$1”test -d $newdir || mkdir $newdircd $newdir
13
Dienstag, 16. August 11
The Bash: Defensive Scripting
Re-use: $()More readable than `backticks`myfiles=$(ls $HOME)
14
Dienstag, 16. August 11
The Bash: Defensive Scripting
Re-use: sourceMore readable than “.”source $HOME/lib/basics.shsource /etc/conf/script.cnf
15
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming• test, test, test (for $?)• find• && and || (AND and OR)• trap• log, stderr• --help, --version, usage()• Use full path names
16
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: testtest -r “$sourcefile”test -d “$destdir”test -x “$script”test -w “$destfile”test -n “$variable”test -z “$nothing”
17
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: testtest -r “$sourcefile”if [[ $? = 0 ]]; then echo “yes, it’s readable”else echo “cannot read $sourcefile”fi
18
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: && and ||test -r “$sourcefile” || exit 1
19
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: && and ||test -r “$sourcefile” || { echo “Cannot read source file” >&2 exit 1}
20
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: && and ||test -r “$sourcefile” && { cat -n “$sourcefile”} || { echo “Cannot read source file” >&2 exit 1}
21
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: findDon’t rely on a file being in some exact place. If it needs to be, tell the user.find Syntax is a bit peculiar.find $install_dir -name “*README*” -type f -exec mv {} $install_dir/docs/ \;
22
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: traptrap “/bin/rm -f $tmpf; exit” EXITtrap “source $config” SIGHUP
23
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: LogsWrite status to stderr. stderr is not for *errors* only, but for all kind of metainformationUse syslog/logger or your own logging function
24
function log () { msg=“$(date) ERR $@” test -w $LOGF && echo $msg > $LOGF echo $msg >&2}
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: --help, --version• Simplify the use of your program by providing --help and --version
• On error print a usage message
25
Dienstag, 16. August 11
The Bash: Defensive Scripting
Defensive Programming: use full path namesbase=$HOME/installsrcf=$base/source.txtdstf=$base/destination.txttest -r $srcf && cp -i $srcf $dstf
26
Dienstag, 16. August 11
The Bash: Defensive Scripting
Readings• Advanced Bash-Scripting Guide http://
tldp.org/LDP/abs/html/• The Art of Unix Programming (by Eric S.
Raymond; http://www.faqs.org/docs/artu/)• Wicked Cool Shell Scripts (No Starch Press)• Patrick Jezek: Bash Techtalk (08/2010)
http://slides.liip.ch/shell_scripting/index.html
27
Dienstag, 16. August 11