Table of Contents
Bash
What is BASH?
BASH stands for the B
ourne A
gain SH
ell, which is based on the UNIX C
Shell and the Korn Shell. It is POSIX2 compliant.
The shell is the way users or scripts communivate with the Kernel. See https://askubuntu.com/questions/161511/are-the-linux-utilities-parts-of-the-kernel-shell for info on shells and kernels.
Bash Config files
Your home directory will containup to 3 files for configuring BASH, the default system wide file is /etc/profile
, but ~/.bash_profile will override this. It is read every time you log in.
~/.bashrc
is run each time you start a subshell.
~/.bash_logout
is run when a login shell exits.
~/.bash_history
is not really a config file, but stores a list of the commands you have run.
Generic script frameworks
Developed over time, these are frameworks which allows me to concentrate on the purpose of the script, the “boilerplate” code is already written and handles the boring stuff such as parsing input, reporting errors and writing log files.
Misc
Print tab character.
tab=$(echo -en “\t”)
bash-3.00$ tab=$(echo -en "\t") bash-3.00$ echo "test $tab test" test test bash-3.00$ echo "test${tab}test" test test bash-3.00$ echo "test${tab}${tab}test" test test bash-3.00$
Specifying the base of a number
value too great for base
probably refers to an arithmetic operation on a single 8 or 9 with a leading 0, ie. 08 or 09. Bash assumes this is an octal number from the leading 0 but 8 & 9 are not legal octal characters.
You can specify the base of a number using base#number
, usage is:-
RTTMP7=$((10#$RTTMP6 + 10#$RTTMP4))
Running multiple commands
Join two or more commands together, just rune them in turn and don't care if they succeed or fail:-
$ command1 ; command2
Logical AND, first command must succeed or second won't get run:-
$ mkdir newdir && cd newdir
Logical OR, runs second command when 1st fails:-
$ [-d newdir ] || mkdir newdir
Combining them:-
$ [-d newdir ] || mkdir newdir && cd newdir
Comparisons
Arithmetic Comparisons | |
---|---|
-lt | < |
-gt | > |
-le | ⇐ |
-ge | >= |
-eq | == |
-ne | != |
String Comparisons | |
---|---|
= | equal |
!= | not equal |
< | less then |
> | greater then |
-n s1 | string s1 is not empty |
-z s1 | string s1 is empty |
Unlike setting variables where a space round the VARIABLE=value
is required, comparison operators NEED a space round the operator, thinking on this, setting a variable and testing it are quite different operations, but the =
and ==
for variable setting and testing numeric equality do superficially look similar.
if elif else
ACTION=${1} if [ "${ACTION}" = "start" ]; then echo "Starting Apache instances" elif [ "${ACTION}" = "stop" ]; then echo "Stopping Apache instances" else echo "No parameter passed, Useage:- startstopapache.sh start|stop" exit 2 fi
if with multiple conditions
#!/bin/bash FABRIC=$1 if [ "${FABRIC}" = "" ] then echo "You need to provide a Fabric number, either 1 or 2" exit 1 fi
AND if [ "${FABRIC}" != "1" ] && [ "${FABRIC}" != "2" ] then echo "Fabric values can only be 1 or 2" fi
OR if [ ${CPRESULT} != 0 ] || [ ${CPUSERRESULT} != 0 ] then THRESHOLD=1 fi
if [ -z "${1}" ] || [ -z "${2}" ]; then printf "Usage:- assumerole.sh <account> <role to assume> \n" exit 1 fi
for loop
Specify a range of variables to work with
for i in {1..5}
for VARIABLE in bar boyl gm ppy or for VARIABLE in `cat FILENAME` do echo "WebSite is ${VARIABLE}, acton is ${ACTION}" done
Exit from loop early
break
causes the loop to quit, continue
just exits the current iteration of the loop, it will just carry on with the next loop iterator value.
# use for loop read all GC servers for (( gc=0; gc<${GCLENGTH}; gc++ )); do echo "Using >${GLOBALCATALOG[$gc]}<" echo "===============================" echo "" ldapsearch -x -L -h ${GLOBALCATALOG[$gc]} -D "${CN}" -W -b "${SEARCHBASE=}" -s sub proxyAddresses LDAPSEARCHRESULT=$? if [ ${LDAPSEARCHRESULT} = 0 ] then break fi done
while loop
while ($line = <SERIAL>) { print "$line\n"; }
Time duration of operation and record exit status
DURATION=$(time (tar -xvzf ${TARLOCATION}/ww-wiki-backup-${DAY}.tar.gz > /dev/null 2>&1) 2>&1) TARRESULT=$? echo "untar result is >${TARRESULT}<, " >> ${TMPLOG} echo -n "Explode return code is >${TARRESULT}<, it took" >> ${TMPLOG} echo "${DURATION}" >> ${TMPLOG} echo "" >> ${TMPLOG}
Remove first or last character from variable
Use #
for start of variable or %
for the end of the variable.
[ scripts]$ FILE=admin.log.bz2
[ scripts]$ echo $FILE admin.log.bz2 [ scripts]$ FILE=${FILE%.bz2} [ scripts]$ echo $FILE admin.log
Getting web page with wget
Basic use:-
$ wget --user='user' --password='pw' 'http://www.yoursite.com/index.html'
wget with login page and cookie is a two stage process. First, login and retreive cookie, secondly use this cookie to download resource:-
$ wget --save-cookies tmpcookies.txt --post-data 'user=user&password=pw' http://www.yoursite.com/login.html $ wget --load-cookies tmpcookies.txt -p http://www.yoursite.com/protectedcontent.html
curl is somewhat similar:-
$ curl -u 'user:pw' 'http://www.yoursite.com'
Spinner.sh
#/bin/bash # written Andrew Stringer 26/07/2013 #Aimlessly spins round waiting for something function spinner() { local delay=0.75 local spinstr='/-\|' printf "...\n" while [ true ]; do local temp=${spinstr#?} printf "[%c]" "$spinstr" local spinstr=$temp${spinstr%"$temp"} sleep $delay printf "\b\b\b" done } echo "Waiting for 10s." echo "================" spinner & LAST_SPINNER_PID=$! sleep 10 kill ${LAST_SPINNER_PID} echo "" echo "Finished!" echo ""
$ ./spinner.sh Waiting for 10s. ================ ... [-] Finished!
Does directory exist
#!/bin/bash DIR=H if [ -d $DIR ]; then echo "Dir $DIR exists" else mkdir H fi
Copy all files between directories
rsync -av src dest
Arrays
Bash array example, indices start at zero, so below [1] returns the second element ('example'):-
$ andrewsArray=(test example "three" 4) $ echo ${andrewsArray[1]} $ for i in ${andrewsArray[@]}; do ./pipeline --value $i done $ andrewsArray+=( "newItem1" "newItem2" )
Change user password from shell script
$ echo 'username:new_password' | sudo chpasswd
sed - stream editor
Remove comments starting with #
from a file.
sed -e "/^#/d" <filename> > outputfile
-e
is the regex expression (tautology noted…), ^
anchors to the start of the line, d
deletes what is matched.
Remove last line of file
sed -i '$d' myfile.txt
-i
allows sed to edit the file in place.
Testing content of zip file
I just want the files in a zip archive, without the Archive
header or testing
prefix added to each line.
Also, as I need to compare zip files from a bash zip command and from a python equivalent, I want to sort them so diff
can compare:-
$ unzip -t /tmp/boto3_python-1.26.59.zip | more Archive: /tmp/boto3_python-1.26.59.zip testing: __pycache__/ OK testing: bin/ OK testing: boto3/ OK testing: boto3-1.26.59.dist-info/ OK
$ unzip -t boto3_python-1.26.59.zip | sed 's/^ testing: //' | sed '/^Archive:/d' | sort > unzup-python-raw.txt
Default value for variable
read -p "AWS region [default is:- eu-west-2]:-" AWS_REGION AWS_REGION=${AWS_REGION:-eu-west-2}
Remove and recreate directory
# remove any existing directories if they match the current release. if [ -d "$LIB_DIR" ]; then rm -rf ${LIB_DIR}; fi mkdir -p ${LIB_DIR}
This page has been accessed:-
Today: 1
Yesterday: 1
Until now: 232