Defer for Shell
March 8, 2020
One of my favourite features of Go is the defer
keyword. It allows for a clean way to cleanup resources upon returning from a function, whilst the statement itself is immediately after or in close proximity to the resource acquisition. This makes the cleanup more visible and can reduce the likelihood of bugs if your function contains many branches.
I think the defer
keyword is so useful that it should be a component of every language. I think C in particular could benefit greatly – freeing locally allocated memory would become trivial.
I decided to implement a pseudo-defer
keyword for shell (/bin/sh
) which simplified some of my scripts. With this, I can be sure that mounts and files are always cleaned up properly, even if the script exits early. This is known as idempotency.
#!/bin/sh
DEFER=
defer() {
DEFER="$*; ${DEFER}"
trap "{ $DEFER }" EXIT
}
Here’s an example of how you can use this function:
# Mount /tmp as tmpfs and umount it on script exit.
mount -t tmpfs tmpfs /tmp
defer umount -f /tmp
# Create a temporary file and delete it on script exit.
TEMP=$(mktemp)
echo "Hello!" > "$TEMP"
defer rm -f "$TEMP"
This might require some tweaking for your particular use-case. If you have any suggestions or comments, please leave them here!