Welcome! In this lesson, we will explore the powerful trap
command in Bash. The trap
command executes a set of commands when a script exits, whether it completes successfully or encounters an error. This command is crucial for managing cleanup operations in your scripts. Proper cleanup ensures that temporary files and other resources do not clutter your system or cause unexpected behaviors.
Let's get started!
The trap
command in Bash allows you to specify commands that should be executed when a certain signal is received by the script. Signals are notifications sent to a process to notify it of various events. For example, the EXIT
signal is sent when the script exits, either normally or due to an error. The INT
(interrupt) signal triggers when you press Ctrl+C
to interrupt the script.
The general syntax for the trap
command in Bash is as follows:
Bash1trap 'commands' signal
This line instructs the script to run commands
when the specified signal
is received. commands
can be a string of commands, another script or a function.
The following script creates a file called temp.txt
then exits. We use the trap
command to remove this temporary file once the script exits.
solution.sh
Bash1#!/bin/bash 2 3# Define a cleanup function 4cleanup() { 5 echo -e "ls command before cleanup... \n$(ls)\n" 6 rm -f temp.txt 7 echo -e "ls command after cleanup... \n$(ls)\n" 8} 9 10# Set up a trap to call the cleanup function on script exit 11trap cleanup EXIT 12 13# Creating a temporary file 14touch temp.txt 15 16# Simulate some work 17echo "Working with temp.txt" 18echo "Done working with temp.txt. It can be cleaned up." 19 20# Exiting script 21exit 0
In this script:
- The
cleanup
function removes temporary files and printsls
output before and afterrm -f temp.txt
. trap cleanup EXIT
: Sets up a trap to call thecleanup
function on script exit.touch temp.txt
: Creates an empty file namedtemp.txt
.- Two
echo
statements simulate work with the temporary file. - When
exit 0
is executed, thetrap
command ensures thecleanup
function is called to remove the temporary file.
The output of the script is:
Plain text1Working with temp.txt 2Done working with temp.txt. It can be cleaned up. 3 4ls command before cleanup... 5solution.sh 6temp.txt 7 8ls command after cleanup... 9solution.sh
The output of the script shows that when the exit 0
command is executed, the cleanup
function is called, successfully removing the temp.txt
. The trap
command ensures that the cleanup function is executed regardless of how the script exits, providing a robust way to manage resources.
The trap
command can handle various signals, not just EXIT
. For instance, the INT
signal is sent when you press Ctrl+C
to interrupt a script. Let’s modify our script to handle the INT
signal as well. This script sets up two cleanup functions: one for handling the EXIT
signal and another for the INT
signal. When the script exits normally, the cleanup_exit
function is invoked. If the user interrupts the script by pressing Ctrl+C
, the cleanup_int
function prints a message indicating that the script was interrupted. However, it does not remove the temporary file.
Bash1#!/bin/bash 2 3# Define cleanup function for EXIT 4cleanup_exit() { 5 echo "EXIT signal received. Cleaning up..." 6 rm -f temp.txt 7} 8 9# Define cleanup function for INT 10cleanup_int() { 11 echo "INT signal received from Ctrl+C. Not removing temp.txt" 12} 13 14# Set traps 15trap cleanup_exit EXIT 16trap cleanup_int INT 17 18# Simulate work 19touch temp.txt 20echo "Working with temp.txt. Press Ctrl+C to interrupt." 21 22# Exiting script 23exit 0
In the script:
cleanup_exit
defines a function that prints a descriptive message and removestemp.txt
cleanup_int
defines a function that prints a descriptive message but does not removetemp.txt
trap cleanup_exit EXIT
instructs the script to callcleanup_exit
if the script receives anEXIT
signaltrap cleanup_int INT
instructs the script to callcleanup_int
if the script receives anINT
signalexit 0
exits the script, sending anEXIT
signal
If the script runs without the user pressing Ctrl+C
, the output is:
Plain text1Working with temp.txt. Press Ctrl+C to interrupt. 2EXIT signal received. Cleaning up...
The temp.txt
no longer exists in the current working directory.
If the user pressed Ctrl+C
, the output is:
Plain text1Working with temp.txt. Press Ctrl+C to interrupt. 2INT signal received from Ctrl+C. Not removing temp.txt.
temp.txt
will still exist in the current working directory.
We can also specify what commands to run based on the exit status. This script sets up two cleanup functions to handle success (cleanup_success
) and failure (cleanup_failure
), and a general cleanup function (cleanup
) to dispatch the appropriate cleanup based on the exit code. It attempts to read a file file.txt
. Depending on if cat file.txt
succeeds or fails, the script exits with the appropriate status, triggering the relevant cleanup function.
Bash1#!/bin/bash 2 3# Define cleanup function for successful exit 4cleanup_success() { 5 echo "Cleaning up after success..." 6 rm -f temp/fail.txt 7 ls temp 8} 9 10# Define a cleanup function for a failure 11cleanup_failure() { 12 echo "Cleaning up after failure..." 13 rm -f temp/success.txt 14 ls temp 15} 16 17# Define a general cleanup function based on exit code 18cleanup() { 19 if [ $? -eq 0 ]; then 20 cleanup_success 21 else 22 cleanup_failure 23 fi 24} 25 26trap cleanup EXIT 27 28# Creating a temporary file for both success and failure scenarios 29echo "The script was a success" > temp/success.txt 30echo "The script failed" > temp/fail.txt 31 32# Simulate work 33echo "Working with temp directory." 34 35# Simulating command that will succeed or error 36# NOTE: Commenting the touch command to will simulate failure 37touch file.txt 38cat file.txt 39 40# Simulate a successful exit or failure 41if [ $? -eq 0 ]; then 42 echo "Simulating success..." 43 exit 0 # Simulate a successful exit code 44else 45 echo "Simulating failure..." 46 exit 1 # Simulates a failure exit code 47fi
-
The
cleanup_success
function prints a success message then callsrm -f fail.txt
to removefail.txt
-
The
cleanup_failure
function prints a failure message then callsrm -f success.txt
to removesuccess.txt
-
The
cleanup
function checks the script's exit status ($?
) and calls eithercleanup_success
orcleanup_failure
based on whether the script exited successfully or with an error. -
trap cleanup EXIT
sets up a trap to call thecleanup
function when the script exits. -
The
cleanup
function checks the script's exit status ($?
) and calls eithercleanup_success
orcleanup_failure
based on whether the script exited successfully or with an error. -
if [ $? -eq 0 ]
checks whether the exit status of the most recent command ($?
) equals 0. -
If successful, the script executes
exit 0
and calls thecleanup
function which callscleanup_success
-
If not successful (non-zero exit status), the script executes
exit 1
. This calls thecleanup
function which calls thecleanup_failure
function
Now let's look at our command that may or may not error.
- If
touch file.txt
is not commented out,cat file.txt
will not error and the$?
special variable will have a value of0
. - If
touch file.txt
is commented out,cat file.txt
will error$?
will have a non-zero value.
If the script includes the touch file.txt
command the output is:
Plain text1Working with tmp directory. 2Simulating success... 3Cleaning up after success... 4success.txt
If the script does not include touch file.txt
, the output is:
Plain text1Working with tmp directory. 2Simulating failure... 3Cleaning up after failure... 4fail.txt
Great job! In this lesson, you learned how to:
- Define cleanup functions to manage resources.
- Use the
trap
command to execute cleanup functions on script exit. - Handle various signals like
EXIT
andINT
with specific cleanup commands. - Manage multiple exit statuses using the
trap
command to ensure proper cleanup for successful and failed script executions.
Now it's time to put your new knowledge into practice! Head over to the practice section to try these concepts on your own. By practicing, you'll gain confidence and become adept at writing scripts that handle resources efficiently. Happy scripting!