this post was submitted on 20 Sep 2026
21 points (95.7% liked)

Programming

28812 readers
227 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 3 years ago
MODERATORS
 

Update: Here is my current corrected version (do not trust blindly, I had typos involved too!)

#!/usr/bin/env bash

TEMPDIR="$(mktemp -d)"
mkdir --verbose -- "${TEMPDIR}/tests"
trap 'cd -- "${TEMPDIR}/tests" && rm --verbose --one-file-system -rf "${TEMPDIR:-/invalid/615e1a5d}/tests"; cd ..; rmdir --verbose -- "${TEMPDIR}"' EXIT

And an alternative variant in case there are only files without subdirectories involved under "tests":

trap 'cd -- "${TEMPDIR}/tests" && rm --verbose --one-file-system -f -- "${TEMPDIR:-/invalid/615e1a5d}/tests/"*; cd ..; rmdir --verbose -- tests "${TEMPDIR}"' EXIT

Note, I use --verbose to explicitly list files, because this is for my Test system. If you copy this construct to use in your own normal scripts, you might want to remove the verbose flags for normal usage.


Down below is old version:

This is just a little small question if this is secure. This script is used to create a fresh test environment that should get deleted when script ends. trap command solves that issue fine. However, I am very, very afraid of doing rm -rf in context of variables, in case the variable happens to become empty due to user error (or later changes in script). So I will do this in multiple steps.

#!/usr/bin/env bash

TEMPDIR="$(mktemp -d)"
mkdir -f -- "${TEMPDIR}/tests"
trap 'cd -- "${TEMPDIR}/tests" && rm -rf tests && cd .. && rmdir -- ${TEMPDIR}' EXIT

# Here follows the script content, creating temporary files and manipulating them...
  1. Use a subdirectory, so the variable is not used by itself. So we have to use ${TEMPDIR}/tests each time instead just ${TEMPDIR}.
  2. When removing all files recursively, first enter into directory with cd, and only if that was successful delete all files recursively with a specific directory name. This should make sure that rm -rf is only executed if the temporary directory even exist and the variable is not resolved to empty.
  3. Off course go up one dir again and then remove the empty directory with rmdir, which will only remove empty directories.

I personally feel confident that this construct is safe, but would like to hear your opinions. Maybe I missed something important. It would be devastating. I don't want to try out various ways to see if one of them is working correctly.


Edit: For anyone who does not create uncontrolled temporary directories, they could just use rm -f tests/* instead, so nothing is deleted recursively. I may go that route and avoid sub-directories in my test folder.

you are viewing a single comment's thread
view the rest of the comments
[–] eleijeep@piefed.social 8 points 3 weeks ago (1 children)

Some solutions:

set -e  
TEMPDIR=$(mktemp -d)  
# script exits if mktemp returns error  

or

TEMPDIR=$(mktemp -d || echo "/invalid")  
# TEMPDIR gets the value "/invalid" if mktemp fails  

or

TEMPDIR=$(mktemp -d)  
TEMPDIR=${TEMPDIR:-"/invalid"}  
# TEMPDIR gets the value "/invalid" if mktemp returns an empty value  

or

TEMPDIR=$(mktemp -d)  
rm -rf ${TEMPDIR:-"/invalid"}  
# rm is passed "/invalid" if TEMPDIR is empty  

My personal preference is the last one. Any time you call rm -rf you provide a default value to variables to ensure that if they are empty they get some other value instead.

[–] thingsiplay@lemmy.ml 0 points 3 weeks ago (1 children)

My reply is rejecting (most of) your suggestions, with reasons off course. I am glad you bring them up, so we can talk about it.

I would avoid set -e option, as I do not want he entire script to exit on error. So instead I can use the exit command when I really want to on specific errors. I rather would like to handle errors myself directly, maybe even not exiting, but displaying error code with $? in example.

TEMPDIR=$(mktemp -d || echo "/invalid")

If anything, it would make more sense to just exit the script with || exit. In fact that is what I'm doing in the script after the trap command by cd "${TEMPDIR}/tests" || exit, so the script never continues without a successful mktemp directory.

TEMPDIR=${TEMPDIR:-"/invalid"}

I always forget that Bash has default values for variables! mktemp actually makes sure it never returns an empty value. I'm not worried about what it returns, but that my script could change the value of $TEMPDIR by accident (in example to something empty). So assigning a default value after mktemp will never have a chance to get the default value at all.

rm -rf ${TEMPDIR:-"/invalid"}

This on the other hand I like a lot. Now I will not stop doing my other additional checks, but for good habit this can't be wrong. Maybe instead a custom directory name with an unlikely name, what about pointing it to /dev/null? I actually like this idea and might incorporate it.

[–] eleijeep@piefed.social 3 points 3 weeks ago (1 children)

rm -rf ${TEMPDIR:-"/invalid"}
This on the other hand I like a lot. Now I will not stop doing my other additional checks, but for good habit this can’t be wrong.

I believe this is considered to be best practise, but I included the other options just for the sake of completeness.

Happy to help.

[–] thingsiplay@lemmy.ml 0 points 3 weeks ago* (last edited 3 weeks ago) (1 children)

What if I would use /dev/null instead /invalid? Do you think this is a problem, better or worse? rm -rf ${TEMPDIR:-/dev/null}. I will update the current solution above, but need some research first. Edit: Oh wait, that could be dangerous if. If the script runs with root privileges, then /dev/null would be deleted.

[–] eleijeep@piefed.social 2 points 3 weeks ago* (last edited 3 weeks ago)

As a regular user that's fine, but if your script might be run as root then there's a possibility that you delete the special file /dev/null which would cause a great deal of problems for your system and probably be hard to debug if you don't realise it has happened. I've heard of people doing this before so I think it is possible although I've never tried it.

Edit: yeah I just saw your edit and I agree :)