10. The Bash: Defensive Scripting
Unix
• Be forgiving in what you accept, but
strict in what you emit
3
Montag, 29. August 11
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
3
Montag, 29. August 11
12. 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
3
Montag, 29. August 11
13. 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
3
Montag, 29. August 11
14. 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
Montag, 29. August 11
16. The Bash: Defensive Scripting
Unix: The Unix Toolbox
4
Montag, 29. August 11
17. The Bash: Defensive Scripting
Unix: The Unix Toolbox
Get 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.
4
Montag, 29. August 11
18. The Bash: Defensive Scripting
Unix: The Unix Toolbox
Get 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/bin
4
Montag, 29. August 11
19. The Bash: Defensive Scripting
Unix: The Unix Toolbox
Get 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/bin
Extend your Unix Toolbox
4
Montag, 29. August 11
33. The Bash: Defensive Scripting
Interfaces: Source
Read from file, write to stdout
7
Montag, 29. August 11
34. The Bash: Defensive Scripting
Interfaces: Source
Read from file, write to stdout
Interface to outer world, beginning of a
pipe sequence
7
Montag, 29. August 11
35. The Bash: Defensive Scripting
Interfaces: Source
Read from file, write to stdout
Interface to outer world, beginning of a
pipe sequence
Example: cat
7
Montag, 29. August 11
38. The Bash: Defensive Scripting
Interfaces: Sink
Read from stdin, write to file
8
Montag, 29. August 11
39. The Bash: Defensive Scripting
Interfaces: Sink
Read from stdin, write to file
Interface to outer world, end of a pipe
sequence
8
Montag, 29. August 11
40. The Bash: Defensive Scripting
Interfaces: Sink
Read from stdin, write to file
Interface to outer world, end of a pipe
sequence
Example: >
8
Montag, 29. August 11
43. The Bash: Defensive Scripting
Interfaces: Cantrip
Do sth. and return nothing but a status
code (or errors)
9
Montag, 29. August 11
44. The Bash: Defensive Scripting
Interfaces: Cantrip
Do sth. and return nothing but a status
code (or errors)
This is super scriptable
9
Montag, 29. August 11
45. The Bash: Defensive Scripting
Interfaces: Cantrip
Do sth. and return nothing but a status
code (or errors)
This is super scriptable
Example: rm
9
Montag, 29. August 11
58. The Bash: Defensive Scripting
Re-use: Functions
Will behave like a script on its own
12
Montag, 29. August 11
59. The Bash: Defensive Scripting
Re-use: Functions
Will behave like a script on its own
function log {
12
Montag, 29. August 11
60. The Bash: Defensive Scripting
Re-use: Functions
Will behave like a script on its own
function log {
echo “$(date) ERR $@” >&2
12
Montag, 29. August 11
61. The Bash: Defensive Scripting
Re-use: Functions
Will behave like a script on its own
function log {
echo “$(date) ERR $@” >&2
}
12
Montag, 29. August 11
62. The Bash: Defensive Scripting
Re-use: Functions
Will behave like a script on its own
function log {
echo “$(date) ERR $@” >&2
}
log “Cannot connect”
12
Montag, 29. August 11
63. The Bash: Defensive Scripting
Re-use: Functions
Will behave like a script on its own
function log {
echo “$(date) ERR $@” >&2
}
log “Cannot connect”
# Do 4 Aug 2011 10:38:58 CEST ERR
Cannot connect 12
Montag, 29. August 11
66. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
13
Montag, 29. August 11
67. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
# file mcd -- make a dir if
13
Montag, 29. August 11
68. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
# file mcd -- make a dir if
# necessary and cd to it
13
Montag, 29. August 11
69. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
# file mcd -- make a dir if
# necessary and cd to it
test -n “$1” || exit 1
13
Montag, 29. August 11
70. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
# file mcd -- make a dir if
# necessary and cd to it
test -n “$1” || exit 1
newdir=”$1”
13
Montag, 29. August 11
71. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
# file mcd -- make a dir if
# necessary and cd to it
test -n “$1” || exit 1
newdir=”$1”
test -d $newdir || mkdir $newdir
13
Montag, 29. August 11
72. The Bash: Defensive Scripting
Re-use: Wrappers
#!/bin/bash
# file mcd -- make a dir if
# necessary and cd to it
test -n “$1” || exit 1
newdir=”$1”
test -d $newdir || mkdir $newdir
cd $newdir 13
Montag, 29. August 11
79. The Bash: Defensive Scripting
Re-use: source
More readable than “.”
15
Montag, 29. August 11
80. The Bash: Defensive Scripting
Re-use: source
More readable than “.”
source $HOME/lib/basics.sh
15
Montag, 29. August 11
81. The Bash: Defensive Scripting
Re-use: source
More readable than “.”
source $HOME/lib/basics.sh
source /etc/conf/script.cnf
15
Montag, 29. August 11
92. The Bash: Defensive Scripting
Defensive Programming: test
17
Montag, 29. August 11
93. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
17
Montag, 29. August 11
94. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
test -d “$destdir”
17
Montag, 29. August 11
95. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
test -d “$destdir”
test -x “$script”
17
Montag, 29. August 11
96. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
test -d “$destdir”
test -x “$script”
test -w “$destfile”
17
Montag, 29. August 11
97. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
test -d “$destdir”
test -x “$script”
test -w “$destfile”
test -n “$variable”
17
Montag, 29. August 11
98. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
test -d “$destdir”
test -x “$script”
test -w “$destfile”
test -n “$variable”
test -z “$nothing”
17
Montag, 29. August 11
100. The Bash: Defensive Scripting
Defensive Programming: test
18
Montag, 29. August 11
101. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
18
Montag, 29. August 11
102. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
if [[ $? = 0 ]]; then
18
Montag, 29. August 11
103. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
if [[ $? = 0 ]]; then
echo “yes, it’s readable”
18
Montag, 29. August 11
104. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
if [[ $? = 0 ]]; then
echo “yes, it’s readable”
else
18
Montag, 29. August 11
105. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
if [[ $? = 0 ]]; then
echo “yes, it’s readable”
else
echo “cannot read $sourcefile”
18
Montag, 29. August 11
106. The Bash: Defensive Scripting
Defensive Programming: test
test -r “$sourcefile”
if [[ $? = 0 ]]; then
echo “yes, it’s readable”
else
echo “cannot read $sourcefile”
fi
18
Montag, 29. August 11
125. The Bash: Defensive Scripting
Defensive Programming: find
22
Montag, 29. August 11
126. The Bash: Defensive Scripting
Defensive Programming: find
Don’t rely on a file being in some exact
place. If it needs to be, tell the user.
22
Montag, 29. August 11
127. The Bash: Defensive Scripting
Defensive Programming: find
Don’t rely on a file being in some exact
place. If it needs to be, tell the user.
find Syntax is a bit peculiar.
22
Montag, 29. August 11
128. The Bash: Defensive Scripting
Defensive Programming: find
Don’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
Montag, 29. August 11
133. The Bash: Defensive Scripting
function log {
msg=“$(date) ERR $@”
test -w $LOGF && echo $msg > $LOGF
echo $msg >&2
}
24
Montag, 29. August 11
134. The Bash: Defensive Scripting
Defensive Programming: Logs
function log {
msg=“$(date) ERR $@”
test -w $LOGF && echo $msg > $LOGF
echo $msg >&2
}
24
Montag, 29. August 11
135. The Bash: Defensive Scripting
Defensive Programming: Logs
Write status to stderr. stderr is not
for *errors* only, but for all kind of
metainformation
function log {
msg=“$(date) ERR $@”
test -w $LOGF && echo $msg > $LOGF
echo $msg >&2
}
24
Montag, 29. August 11
136. The Bash: Defensive Scripting
Defensive Programming: Logs
Write status to stderr. stderr is not
for *errors* only, but for all kind of
metainformation
Use syslog/logger or your own logging
function function log {
msg=“$(date) ERR $@”
test -w $LOGF && echo $msg > $LOGF
echo $msg >&2
}
24
Montag, 29. August 11
138. The Bash: Defensive Scripting
Defensive Programming:
25
Montag, 29. August 11
139. The Bash: Defensive Scripting
Defensive Programming:
--help, --version
25
Montag, 29. August 11
140. The Bash: Defensive Scripting
Defensive Programming:
--help, --version
• Simplify the use of your program by
providing --help and --version
25
Montag, 29. August 11
141. 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
Montag, 29. August 11
143. The Bash: Defensive Scripting
Defensive Programming:
26
Montag, 29. August 11
144. The Bash: Defensive Scripting
Defensive Programming:
use full path names
26
Montag, 29. August 11
145. The Bash: Defensive Scripting
Defensive Programming:
use full path names
base=$HOME/install
26
Montag, 29. August 11
146. The Bash: Defensive Scripting
Defensive Programming:
use full path names
base=$HOME/install
srcf=$base/source.txt
26
Montag, 29. August 11
147. The Bash: Defensive Scripting
Defensive Programming:
use full path names
base=$HOME/install
srcf=$base/source.txt
dstf=$base/destination.txt
26
Montag, 29. August 11
148. The Bash: Defensive Scripting
Defensive Programming:
use full path names
base=$HOME/install
srcf=$base/source.txt
dstf=$base/destination.txt
test -r $srcf && cp -i $srcf $dstf
26
Montag, 29. August 11
151. The Bash: Defensive Scripting
Readings
• Advanced Bash-Scripting Guide http://
tldp.org/LDP/abs/html/
27
Montag, 29. August 11
152. 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/)
27
Montag, 29. August 11
153. 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)
27
Montag, 29. August 11
154. 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
Montag, 29. August 11