170

If a Bash script has set -e, and a command in the script returns an error, how can I do some cleanup before the script exits?

For example:

#!/bin/bash
set -e
mkdir /tmp/foo
# ... do stuff ...
rm -r /tmp/foo

How can I ensure that /tmp/foo is removed, even if one of the commands in ... do stuff ... fails?

codeforester
  • 39,467
  • 16
  • 112
  • 140
David Wolever
  • 148,955
  • 89
  • 346
  • 502

5 Answers5

282

Here's an example of using trap:

#!/bin/bash -e

function cleanup {
  echo "Removing /tmp/foo"
  rm  -r /tmp/foo
}

trap cleanup EXIT
mkdir /tmp/foo
asdffdsa #Fails

Output:

dbrown@luxury:~ $ sh traptest
t: line 9: asdffdsa: command not found
Removing /tmp/foo
dbrown@luxury:~ $

Notice that even though the asdffdsa line failed, the cleanup still was executed.

030
  • 10,842
  • 12
  • 78
  • 123
devguydavid
  • 3,917
  • 1
  • 19
  • 18
  • 1
    To whom it may concern: This will also be executed when someone uses Ctrl+D or `exit` to end the current bash session. – Qqwy Aug 02 '22 at 18:37
  • Using `trap cleanup EXIT`, the *cleanup* function will **also** execute if the "command in the script does **not** return an error".... On the other hand, using e.g. `trap cleanup ERR` will execute the *cleanup* function only when there is an error, it will not execute if there is no error . Further information in https://stackoverflow.com/a/26261518/923560 – Abdull May 10 '23 at 11:52
16

From the bash manpage (concerning builtins):

trap [-lp] [[arg] sigspec ...]
The command arg is to be read and executed when the shell receives signal(s) sigspec.

So, as indicated in Anon.'s answer, call trap early in the script to set up the handler you desire on ERR.

Community
  • 1
  • 1
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
14

sh version of devguydavid's answer.

#!/bin/sh
set -e
cleanup() {
  echo "Removing /tmp/foo"
  rm  -r /tmp/foo
}
trap cleanup EXIT
mkdir /tmp/foo
asdffdsa #Fails

ref: shellscript.sh

Saftever
  • 685
  • 6
  • 9
10

From the reference for set:

-e

Exit immediately if a simple command (see section 3.2.1 Simple Commands) exits with a non-zero status, unless the command that fails is part of an until or while loop, part of an if statement, part of a && or || list, or if the command's return status is being inverted using !. A trap on ERR, if set, is executed before the shell exits.

(Emphasis mine).

Anon.
  • 58,739
  • 8
  • 81
  • 86
1

I don't know if it matters to you if it's before or after.

You can set a script to run immediately after closing with "trap". and then you can close the terminal.

For Example;

    trap  ./val.sh EXIT  #set command you want to run after close terminal 
    kill -9 $PPID        #kill current terminal