| Bri Hatch | Personal | Work |
|---|---|---|
|
Onsight, Inc bri@ifokr.org |
ExtraHop Networks bri@extrahop.com |
set -x
$ cat script.sh #!/bin/bash echo "Hello World" date $ ./script.sh Hello World Fri 05 Nov 2021 10:32:00 PM UTC $ sh -x ./script.sh + echo Hello World Hello World + date Fri 05 Nov 2021 10:32:08 PM UTC
$ nl -ba script.sh 1 #!/bin/bash 2 echo "Hello World" 3 set -x 4 date 5 set +x 6 echo "Debugging is off again" $ ./script.sh Hello World + date Fri 05 Nov 2021 10:35:43 PM UTC +set +x Debugging is off again
$ cat script.sh #!/bin/bash echo "Hello $USER!" echo "Your home dir is $HOME!" echo "You logged in from $SSH_CLIENT" $ ./cat script.sh Hello wendell! Your home dir is /home/wendell You logged in from $ echo $? 1
$ cat script.sh #!/bin/bash set -u echo "Hello $USER!" echo "Your home dir is $HOME!" echo "You logged in from $SSH_CLIENT" $ ./cat script.sh Hello wendell! Your home dir is /home/wendell script.sh line 5: SSH_CLIENT: unbound variable $ echo $? 1
$ cat script.sh
#!/bin/bash
set -u
echo "Hello $USER!"
echo "Your home dir is $HOME!"
echo "You logged in from ${SSH_CLIENT:-something other than ssh}"
$ ./cat script.sh
Hello wendell!
Your home dir is /home/wendell
You logged in from something other than ssh
${variable:-value}
${variable:=value}Many other options, including substrings, substitutions.
Warning: Use only where it improves readability!
set -e causes processing to stop immediately if a
command in your script fails.
Allows you to remove a lot of if...then logic
#!/bin/bash
...
if ! touch "$tmpfile" ; then
echo "Could not create $tmpfile"
fi
...
vs
#!/bin/bash set -e ... touch "$tmpfile"
set -e
#!/bin/bash set -e echo -n "What file should I create?" read filename # Use "or true" rm "$filename" || true # or use "force" features if available rm -f "$filename"
set -e only looks at the rightmost command exit status. Use set -o pipefail to bail on command failures in pipelines too.
#!/bin/bash
set -e
set -o pipefail
echo -n "Who's logged into the console? "
w | grep " :0 " | awk '{print $1}'
...
If no one is logged in on console the code will stop at the w line because grep will fail.
trap
#!/bin/bash
set -o
set -e
tmpfile=""
cleanup () {
if [ -f "$tmpfile" ] ; then
rm "$tmpfile"
fi
}
trap cleanup EXIT
tmpfile=$(mktemp)
...
#!/bin/bash
breaks_required=3
warn () {
if [ "$breaks_required" -gt 0 ] ; then
echo "Quitting this process is not a good idea." >&2
echo "Hit <ctrl-c>> $breaks_required more times to really quit." >&2
breaks_required=$(( $breaks_required - 1 ))
else
exit 1
fi
}
trap warn INT
while : ; do
sleep 20 # This process is killed when you <ctrl-c> !!
echo sleeping again
done
#!/bin/bash
atexit () {
if [ $? -eq 0 ] ; then
echo "Success!" >&2
else
echo "SCRIPT FAILURE!" >&2
fi
# Script will still exit with whatever status
# it was going to use
}
trap atexit EXIT
# Exit 0, 1, or 2 randomly
exit $(( $(date +%s) % 3 ))
#!/bin/bash TOP=$(dirname "$0") file1=$1 file2=$2 # include some related code source "$TOP"/some_config.sh # call some program by reference "$TOP"/../otherscripts/tool.sh
#!/bin/bash # stash the full pathname to the filename args we're sent file1=$(realpath $1) file2=$(realpath $2) # Go to our software's directory cd $(dirname "$0") # include some related code source ./some_config.sh # call some program by reference ../otherscripts/tool.sh
#!/bin/bash
now () {
echo $(date +"%Y-%m-%d-%H:%M:%S")
}
log () {
echo -n $(now) "$1: "
shift
echo "$@" >&2
}
info () { log " INFO" "$@"
}
warn () { log "WARNING" "$@"
}
info "Script starting"
sleep 20
info "20 seconds passed"
warn "But in covid, time has no meaning."
$ ./script.sh 2021-11-05-10:49:00 INFO: Script starting 2021-11-05-10:49:20 INFO: 20 seconds passed 2021-11-05-10:49:20 WARNING: But in covid, time has no meaning.
#!/bin/bash
usage () {
cat <<EOM >&2
Usage: $0 [-n] filename [filename ...]
This script frobs files, unless the -n flag is set.
EOM
if [ "$#" -gt 0 ] ; then
echo "ERROR: $@" >&2
fi
exit 1
}
if [ $# -lt 1 ] ; then
usage Need one or more filenames
fi
...
getopts for user friendly command line options
while getopts hH:dv c; do
case "$c" in
h) usage;;
H) hostname=$OPTARG;;
d) debug=1;;
v) verbose=1;;
esac
done
$ ./script.sh -H baggsend -v
--long optionsshellcheck>&2 to send debug info to stderr
| Personal | Work |
|---|---|
| Bri Hatch Onsight, Inc bri@ifokr.org |
Bri Hatch |
Copyright 2021, Bri Hatch, Creative Commons BY-NC-SA License
for color in $(seq 0 255); do
tput setaf $color
echo $color looks like this
done | less -R
tput sgr0 # Reset all the things
0 looks like this
1 looks like this
2 looks like this
3 looks like this
4 looks like this
5 looks like this
6 looks like this
7 looks like this
man terminfo for all options, including highlighting. See
Color lists
for full list, Run tput colors to see how many are available.
TERM=xterm-256color may give you more....
$ SSH_AUTH_SOCK='' ssh remoteserver $ date Fri 05 Nov 2021 3:52:00 PM PDT $ TZ=UTC date Fri 05 Nov 2021 10:52:00 PM UTC
$ vi script.sh # make changes :wq $ ./script.sh # check it $ vi script.sh # make changes :wq $ ./script.sh
$ vi script.sh # make changes
:w # write changes
<ctrl-z> # drop back to shell
$ ./script.sh # check it
$ fg # back in vim where you were
# same buffers, undo, etc
# make more changes
:w # write changes
<ctrl-z> # drop back to shell
$ ./script.sh # check it
Related: jobs, bg, fg %jobnum
$ PS1='$? \u@\h:\w \$ ' 0 wendell@baggsend:/home/wendell/scripts $ true 0 wendell@baggsend:/home/wendell/scripts $ false 1 wendell@baggsend:/home/wendell/scripts $
:(){:|:&};: