Midwest PHP 2018 Header

Chris explained why we should be using scripting to automate tasks and then when into why to use BASH and some basic examples.

Main Take Aways

It’s easy to get started with BASH scripting but it’s important to know some scripts might be better written in higher level languages. I know I’ve written several in PHP when I needed to use objects from my applications.

Things I’m Going to Do

Try to automate more things using BASH. I already use it in a very limited capacity but this made me want to do more.

My Raw Notes

  • Command line has a lot of power
  • “Internet held together by bash scripts and hope”

Why use bash

  • Ultra-portable - truly write once run anywhere
  • “Automation is the key to making your life easier”

Anatomy of a script

#!/bin/bash

// logic
echo "Hello Worth"

exit 0 // default exit of zero - 0 indicates everything worked

Variables

  • Can’t be a space between variable, equal, and value
MY_VAR="something"
MY_NUMBER=1

Using Variables

APP_LOG=${LOG_DIR}
echo $MY_VAR
echo ${MY_VAR} // suggested method

Declaring Arrays

FILES=(
    'app.log'
    'app.err'
)

echo ${FILES[0]}

Hashes

declare -A ANIMALS
ANIMALS["moo"]="cow"
ANIMALS["dog"]="woof"

echo ${ANIMALS[moo]} // no quotes because consistency is key in programming languages

Storing output

FILES=`ls /var/log` #backtick operator
FILE_DATA=$(cat /var/log/app.log) # recommended for newer shells

Built in variables

  • $0, $1 … -> positional parameters
  • $# -> number of arguments
  • $? -> Exit code of the last command
  • $! -> PID of lat job run int background
  • $@ -> All arguments as quote delimited works # useful for debugging

http://tldp.org/LDP/abs/html/internalvariables.html for all variables

Numerical Comparisons

  • -eq - Equal to
  • -ne - Not equal to
  • -gt, >
  • -gt, >=
  • -lt, <
  • -le, <=

Chris recommends using the flag version because it causes less problems converting numbers to strings

String Comparsion

  • ==, =
  • !=
  • <
  • -n Not null # null is not actually a data type
  • -z Is null, 0 length

Logic Operators

  • &&, -a
  •   , -o
Note: && and   short circuit (i.e. runs in order of operation)

if/else

if [[ ${My_VAR} -eq 0 ]]; then # ; is optional but should be entered to make it easier to read
    #thing
elif [[ ${My_var} -eq 1 ]]; then # must have space between condition and brackets
    #thing
else
    #another thing
fi

Case

case ${my_var} in 
    1) thing ;;
    2) thing ;;
    *) default ;;
esac

For Each Loops

for FILENAME in ${FILES[@]}; do
    echo ${FILENAME}
done

While Loops

COUNTER=0
while [[ ${COUNTER} -lt 10]];
do
    ((COUNTER++)) # double parents -> math operation
done

Functions

function hello_world()
{
    echo "thing"
}

hello_world # when invoking leave off the parens

Arguments

function app_log()
{
    echo "[$(date)] ${1}" #[$(date)] prints the date
}

app_log "This is my log message"

Functions return values

function check_zero()
{
    if [[ ${1} -eq 0 ]]; then
        return 1
    else
        return 0
    fi
}

IS_ZERO=`check_zero 1`

Variable Scope

  • By default everything is global even in a function. Can use local MY_VAR="hello world" to create local functions.
  • Reverse of PHP where everything is local

https://google.github.io/styleguide/shell.xml

For structing larger scripts

  • Define functions at the top
  • Or Break functions out into their own files
    • source filename.sh
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then 
# This script is being invoked as a script 
    echo 'This script is not intended to be run standalone. Please use with the system-micro.sh script' 
    exit 1
fi 

Know when to use a higher level language

  • Complex data
  • Don’t want to rebuild stuff from scratch - no library support in bash