Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

It's well known fact that extra space in env.variable can lead to deletion of / directory in bash script.

#!/bin/bash
...
rm -rf /$MYPATH

if $MYPATH contains values like " dir" or "dir /" it will lead to "rm -rf / dir" or "rm -rf dir /". And will result into "rm -rf /"

Are there any best practices to prevent this situation?

share|improve this question
    
Solaris 10 will not let you do rm -rf / rm of / is not allowed –  Iain Nov 9 '10 at 14:50

9 Answers 9

up vote 10 down vote accepted
alias rm='rm --preserve-root'

IIRC --preserve-root is the default in newer versions of coreutils.

share|improve this answer
4  
In Bash, unless you do shopt -s expand_aliases aliases aren't expanded inside scripts. Also, aliasing rm is a bad idea - what if you're depending on the aliased behavior and the alias isn't there? Some versions of rm may not have --preserve-root. –  Dennis Williamson Nov 9 '10 at 15:37

Always quote your arguments. Even when you know they are sane, it almost never hurts to quote them in scripts.

rm -rf "/$FOO" will not delete / if $FOO has a leading space, instead you'll just not delete anything. This does require the quotes to be present on the line with rm -rf, of course, not something like:

TODEL="/$FOO"
rm -rf $TODEL

If you do that, you'll be back in a whole load of trouble.

Also, I tend to think a good ol':

if [ -d "/$FOO" ] ; then
    ...
fi

(Or -e if it's just a file) is always a good idea before deleting anything.

share|improve this answer

Sanity check your code first. Seriously, anything anyone will tell you will just be something equivalent to the check you should have done inside your code to check the value of $MYPATH. If the script is running interactively, you could remove the -f.

share|improve this answer

First things first: have backups. :-)

But while I hack up those potentially dangerous scripts, I always first echo the dangerous lines, so I can see what would happen.

You can also add a file named -i to important directories, so in some situations rm would prompt while trying to remove those. Of course, if you do the deletion via some other method, such as Perl script or even with different rm parameters, that would not help.

It's also possible to set immutable flag to important files and dirs with chattr +i, but be careful with that one. That can bite you if you actually should remove files from some directory or modify the files ...

share|improve this answer

One way to avoid the issue would be to use an OS that prevents such a command to succeed by design as it is arguably non POSIX compliant. It was initiated by Solaris 10 (2005), followed by BSD then Gnu rm in 2006.

share|improve this answer

You can trim the MYPATH variable before executing the rm command. Just use echo:

MYPATH=`echo $MYPATH`
share|improve this answer
    
be aware that this will also convert any whitespace inside $MYPATH to single spaces, possibly corrupting it... (it applies the shell's word-splitting to the value, and then reconstructs it by appending the words, with spaces in between...) –  r00t Dec 20 '10 at 19:05

After an embarrassing incident many years ago on an Ultrix box, where I did as root a userdel -r sccs (or Ultrix equivalent, it's been a long time) without checking what the sccs user's home directory was beforehand, and the sccs user's $HOME turned out to be /, and the file system went away, I've avoided putting rm -rf $ANYTHING in scripts. You can check the variable until you're blue in the face, but I tend instead to print out a message like "if you're happy with the idea, you should now run sudo rm -rf $ANYTHING".

share|improve this answer
    
How about cleaning up the backups done by rsync? –  igorp1024 Nov 9 '10 at 11:27
    
Sorry, I'm not sure I understand the question. –  MadHatter Nov 9 '10 at 12:56
    
I mean that telling user to run a "rm" command is not a good idea if you need automation (for example, deleting directory after rsync ant tar finished their job). But it's a good point for user's scripts. –  igorp1024 Nov 11 '10 at 6:41

You could pass MYPATH through sed and check that what you put in is that same as what you get out

MYPATH1=`echo "$MYPATH" | sed -e 's|[ \t]\/[ \t]| |' -e 's|^/[ \t]| |' -e 's|[ \t]/$| |' `
if [ "$MYPATH" != "$MYPATH1" ]
then
    dosomething 
fi
share|improve this answer

You're doing a really funny thing here by taking what looks like a relative path and turning it into an absolute one. Treating the given path as the given path is a good start towards accomplishing what you want, but take other commenters' advice and definitely quote everything.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.