Use the trap statement to catch signals and handle errors

From Linux Shell Scripting Tutorial - A Beginner's handbook
Jump to: navigation, search
← Include trap statements in a scriptHomeWhat is a Subshell? →

You can define 'functions' in scripts using the following syntax:

die(){
  echo "An error occurred." 
  exit 2
}

You can simply call it as normal command:

die

You can pass arguments to function:

#!/bin/bash
# define var
file="/tmp/data.$$"
# create function
die(){
  echo "$@" 
  exit 2
}
 
# ... call die if needed
[ ! -f $file ] && die "$0: File $file not found." || echo "$0: File $file found."

The trap command and functions

You can use the trap command with shell functions as follows:

# define die()
die(){
  echo "..."
}

# set trap and call die()
trap 'die' 1 2 3 15
....
...

The following is an updated shell script from how to clear a trap section:

#!/bin/bash
# Shell script to find out odd or even number provided by the user
# set variables to an integer attribute
declare -i times=0
declare -i n=0
 
# define function
warning(){
  echo -e "\n*** CTRL+C and CTRL+Z keys are disabled. Please enter number only. Hit [Enter] key to continue..."
}
 
# capture CTRL+C, CTRL+Z and quit singles using the trap
trap 'warning' SIGINT SIGQUIT SIGTSTP
 
# set an infinite while loop
# user need to enter -9999 to exit the loop
while true
do
	# get date
	read -p "Enter number (-9999 to exit) : " n
 
	# if it is -9999 die 
	[ $n -eq -9999 ] && { echo "Bye!"; break; }
 
	# $n is 0, just get next number
	[ $n -eq 0 ] && continue
 
	# find out if $n is odd or evern
	ans=$(( n % 2 ))
 
	# display result 
	[ $ans -eq 0 ] && echo "$n is an even number." || echo "$n is an odd number."
 
	# increase counter by 1
	times=$(( ++times ))
done
 
# reset all traps 
trap - SIGINT SIGQUIT SIGTSTP
 
# display counter
echo "You played $times times."
exit 0

The following example, add a user to the Linux system by updating /etc/passwd file and creating home directory at /home for user. It traps various single to avoid errors while creating user accounts. If user pressed CTRL+C or script terminated it will try to rollback changes made to system files. Traps are turned on before the useradd command in shell script, and then turn off the trap after the chpasswd line.

#!/bin/bash
# setupaccounts.sh: A Shell script to add user to the Linux system.
# set path to binary files
ADD=/usr/sbin/useradd
SETPASSWORD=/usr/sbin/chpasswd
USERDEL=/usr/sbin/userdel
# set variables 
HOMEBASE=/home
HOMEDIR=""
username=""
 
# define function to clean up useradd procedure 
# handle errors using this function
clean_up_useradd(){
    # remove dir
	[ -d $HOMEDIR ]  && /bin/rm -rf $HOMEDIR
	# remove user from passwd if exits
	grep -q "^${username}" /etc/passwd && $USERDEL ${username}
	# now exit
	exit
}
 
# make sure script is run by root else die 
[ $(id -u) -eq 0 ] || { echo "$0: Only root may add a user or group to the system."; exit 1;}
 
# get username and password 
read -p "Enter user name : " username
 
# create homedir path
HOMEDIR="${HOMEBASE}/${username}"
 
# capture 0 2 3 15 signals
# if script failed while adding user make sure we clean up mess from 
# /home directory and /etc/passwd file
# catch signals using clean_up_useradd()
trap 'clean_up_useradd' SIGINT SIGQUIT SIGTERM
 
# get password
read -sp "Enter user password : " password 
 
# make sure user doesn't exits else die
grep -q "^${username}" /etc/passwd && { echo "$0: The user '$username' already exits."; exit 2;}
 
 
# create a home dir
echo "Creating home directory for ${username} at ${HOMEDIR}..."
[ ! -d ${HOMEDIR} ] && mkdir -p ${HOMEDIR}
 
# Add user
echo "Adding user ${username}..."
${ADD} -s /bin/bash -d ${HOMEDIR} ${username} || { echo "$0: User addition failed."; exit 3; }
 
 
# Set a password
echo "Setting up the password for ${username}..."
#printf "%s|%s\n" $username $password | ${SETPASSWORD} || { echo "$0: Failed to set password for the user."; exit 3; }
echo "$username:$password" | ${SETPASSWORD} || { echo "$0: Failed to set password for the user."; exit 3; }
 
# reset all traps 
trap - 0 SIGINT SIGQUIT SIGTERM
 
# add rest of the script...

You can run this script as follows: chmod +x setupaccounts.sh ./setupaccounts.sh Sample outputs:

Enter user name : testuser
Enter user password : Creating home directory for testuser at /home/testuser...
Adding user testuser...
Setting up the password for testuser...
← Include trap statements in a scriptHomeWhat is a Subshell? →