Shell Scripting Notes

From The System Administrator Zone

Checking the exit status of the last command

The variable $? contains the numeric status returned by the kernel. Zero means success, non-Zero means a failure.

if [ $? -eq 0 ]
then
     etc...
fi

Sorting by Columns

To sort the password file, based on the UID column, you would use

sort -n -t: -k 3 /etc/passwd > /tmp/password-sorted
  • -n -- use numeric sorting
  • -t -- assume ":" are column separators
  • -k -- sort on the third column

A fun usage would be to merge two password files.

cat password1 password2 | sort -n -t: -k3 | uniq > password-new

Using the current process id - $$

This is very useful for constructing temporary files.

TMP=/tmp/testfile00-$$
trap "rm -f $tmp /tmp/testfile01-$$ /tmp/testfile02-$$"
trap exit 1 2 13 15
Test_Program >$TMP

Daisy chaining commands

A successful command will return an exit value of zero when it completes.

We can run command2 if command1 succeeds:

command1 && command2 

command2 is executed if, and only if, command1 returns an exit status of zero.

Or we can run command2 if command1 one fails:

command1 || command2 

command2 is executed if and only if command1 returns a non-zero exit status.

The return status of AND and OR lists is the exit status of the last command executed in the list.

Creating a Custom Date

export DATE=`date +%Y%m%d`
echo $DATE
20080704

This will look like this 20080704. I use this format so that the natural sorting method will sort them correctly. It can be used in a file name list this;

${DUMPDIR}/${DATE}-${db}.sql

Naming a file based on the Day of the Week

This loop will perform a MySQL dump to a file whose name is based on the day of the week.

# dump the MySql files using the Day of the week
for DB in $DB1 $DB2
do
   # --add-drop-table
   # Add a DROP TABLE statement before each CREATE TABLE statement. 
   # This allows the restore function to succeed.
   mysqldump --database $DB -u $USR -p${PD} --add-drop-table > ${DB}-${DAY}.sql
done

The script assumes that there are two databases, $DB1 and $DB2, one user, $USR, and one password, $PD.

The $DAY variable is created this way;

DAY=`date +%A`

The basic idea is to have seven daily dumps on the local disk. The long term archiving will be handled by the system backups. Each daily dump will overwrite the dump from the previous week.

Getting Input from the User

Prompt for user input, assign this to the variable name and then echo the value to standard output.

echo "Please enter your name:"
read name
echo "$name"

To enter more than one word, each word should be assigned to a different variable. Any words left over are assigned to the last named variable. For example:

echo "Please enter your last name followed by your first name: (middle name is optional)\c"
read name1 name2
echo "$name2 $name1"

How to Add a Keyboard Interrupt to a Loop

You can use the -t option to the read command in bash.

#!/bin/bash
count=0
while true
do
        echo count = $count
        ((count=count+1))
        read -t 10 && break
done
echo exited while loop
exit 0

The "count" in this sample is simply there to change the display during each iteration. If the user presses return within 10 seconds, the read succeeds, otherwise it fails. The -t works with bash, sh and most versions of ksh do not have it.

How to Check for an Empty Variable

You often need to check to see if a variable has been set or has a value other than an empty string. This can be done using the -n or -z string comparison operators.

The -n operator checks whether the string is not null. It will return true for every case except where the string contains no characters.

VAR="test"
if [ -n "$VAR" ]; then
    echo "VAR is not empty"
else
    echo "VAR is empty"
fi

Similarly, the -z operator checks whether the string is null. ie:

VAR=""
if [ -z "$VAR" ]; then
    echo "VAR is empty"
else
    echo "VAR is not empty"
fi

Here is part of a real word example where we are testing to see if a program is still running and killing it if it is.

'restart')
        cd ${TMPDIR}
        # added -force as sometimes this seemed to fail - 10/09/2012 - revc
        ${LMBIN}/lmutil lmdown -q -c ${LICDIR}/gt-power.dat -force
        echo sleep 60 seconds
        sleep 60s
        PID=`ps auxww | grep 'GT-Power/lmgrd' | grep 'force' | cut -d" " -f5`
        if [ -n "$PID" ]
        then
                echo Killing PID $PID
                kill -9 $PID
        fi
        start "$PROG"
        exit 0
        ;;