How do I prevent accidental rm -rf /*?
I just ran rm -rf /*
accidentally, but I meant rm -rf ./*
(notice the star after the slash).
alias rm='rm -i'
and --preserve-root
by default didn't save me, so are there any automatic safeguards for this?
I wasn't root and cancelled the command immediately, but there were some relaxed permissions somewhere or something because I noticed that my Bash prompt broke already. I don't want to rely on permissions and not being root (I could make the same mistake with sudo
), and I don't want to hunt for mysterious bugs because of one missing file somewhere in the system, so, backups and sudo
are good, but I would like something better for this specific case.
About thinking twice and using the brain. I am using it actually! But I'm using it to solve some complex programming task involving 10 different things. I'm immersed in this task deeply enough, there isn't any brain power left for checking flags and paths, I don't even think in terms of commands and arguments, I think in terms of actions like 'empty current dir', different part of my brain translates them to commands and sometimes it makes mistakes. I want the computer to correct them, at least the dangerous ones.
One of the tricks I follow is to put #
in the beginning while using the rm
command.
root@localhost:~# #rm -rf /
This prevents accidental execution of rm
on the wrong file/directory. Once verified, remove #
from the beginning. This trick works, because in Bash a word beginning with #
causes that word and all remaining characters on that line to be ignored. So the command is simply ignored.
OR
If you want to prevent any important directory, there is one more trick.
Create a file named -i
in that directory. How can such a odd file be created? Using touch -- -i
or touch ./-i
Now try rm -rf *
:
sachin@sachin-ThinkPad-T420:~$ touch {1..4}
sachin@sachin-ThinkPad-T420:~$ touch -- -i
sachin@sachin-ThinkPad-T420:~$ ls
1 2 3 4 -i
sachin@sachin-ThinkPad-T420:~$ rm -rf *
rm: remove regular empty file `1'? n
rm: remove regular empty file `2'?
Here the *
will expand -i
to the command line, so your command ultimately becomes rm -rf -i
. Thus command will prompt before removal. You can put this file in your /
, /home/
, /etc/
, etc.
OR
Use --preserve-root
as an option to rm
. In the rm
included in newer coreutils
packages, this option is the default.
--preserve-root
do not remove `/' (default)
OR
Use safe-rm
Excerpt from the web site:
Safe-rm is a safety tool intended to prevent the accidental deletion of important files by replacing /bin/rm with a wrapper, which checks the given arguments against a configurable blacklist of files and directories that should never be removed.
Users who attempt to delete one of these protected files or directories will not be able to do so and will be shown a warning message instead:
$ rm -rf /usr Skipping /usr
Your problem:
I just ran rm -rf /* accidentally, but I meant rm -rf ./* (notice the star after the slash).
The solution: Don't do that! As a matter of practice, don't use ./
at the beginning of a path. The slashes add no value to the command and will only cause confusion.
./*
means the same thing as *
, so the above command is better written as:
rm -rf *
Here's a related problem. I see the following expression often, where someone assumed that FOO
is set to something like /home/puppies
. I saw this just today actually, in the documentation from a major software vendor.
rm -rf $FOO/
But if FOO
is not set, this will evaluate to rm -rf /
, which will attempt to remove all files on your system. The trailing slash is unnecessary, so as a matter of practice don't use it.
The following will do the same thing, and is less likely to corrupt your system:
rm -rf $FOO
I've learned these tips the hard way. When I had my first superuser account 14 years ago, I accidentally ran rm -rf $FOO/
from within a shell script and destroyed a system. The 4 other sysadmins looked at this and said, 'Yup. Everyone does that once. Now here's your install media (36 floppy disks). Go fix it.'
Other people here recommend solutions like --preserve-root
and safe-rm
. However, these solutions are not present for all Un*xe-varients and may not work on Solaris, FreeBSD & MacOSX. In addition, safe-rm
requires that you install additional packages on every single Linux system that you use. If you rely on safe-rm
, what happens when you start a new job and they don't have safe-rm
installed? These tools are a crutch, and it's much better to rely on known defaults and improve your work habits.
Since this is on "Serverfault", I'd like to say this:
If you have dozens or more servers, with a largish team of admins/users, someone is going to rm -rf
or chown
the wrong directory.
You should have a plan for getting the affected service back up with the least possible MTTR.
The best solutions involve changing your habits not to use rm
directly.
One approach is to run echo rm -rf /stuff/with/wildcards*
first. Check that the output from the wildcards looks reasonable, then use the shell's history to execute the previous command without the echo
.
Another approach is to limit the echo
command to cases where it's blindingly obvious what you'll be deleting. Rather than remove all the files in a directory, remove the directory and create a new one. A good method is to rename the existing directory to DELETE-foo
, then create a new directory foo
with appropriate permissions, and finally remove DELETE-foo
. A side benefit of this method is that the command that's entered in your history is rm -rf DELETE-foo
.
cd ..
mv somedir DELETE-somedir
mkdir somedir # or rsync -dgop DELETE-somedir somedir to preserve permissions
ls DELETE-somedir # just to make sure we're deleting the right thing
rm -rf DELETE-somedir
If you really insist on deleting a bunch of files because you need the directory to remain (because it must always exist, or because you wouldn't have the permission to recreate it), move the files to a different directory, and delete that directory.
mkdir ../DELETE_ME
mv * ../DELETE_ME
ls ../DELETE_ME
rm -rf ../DELETE_ME
(Hit that Alt+. key.)
Deleting a directory from inside would be attractive, because rm -rf .
is short hence has a low risk of typos. Typical systems don't let you do that, unfortunately. You can to rm -rf -- "$PWD"
instead, with a higher risk of typos but most of them lead to removing nothing. Beware that this leaves a dangerous command in your shell history.
Whenever you can, use version control. You don't rm
, you cvs rm
or whatever, and that's undoable.
Zsh has options to prompt you before running rm
with an argument that lists all files in a directory: rm_star_silent
(on by default) prompts before executing rm whatever/*
, and rm_star_wait
(off by default) adds a 10-second delay during which you cannot confirm. This is of limited use if you intended to remove all the files in some directory, because you'll be expecting the prompt already. It can help prevent typos like rm foo *
for rm foo*
.
There are many more solutions floating around that involve changing the rm
command. A limitation of this approach is that one day you'll be on a machine with the real rm
and you'll automatically call rm
, safe in your expectation of a confirmation… and next thing you'll be restoring backups.
You could always do an alias, as you mentioned:
what_the_hell_am_i_thinking() {
echo "Stop." >&2
echo "Seriously." >&2
echo "You almost blew up your computer." >&2
echo 'WHAT WERE YOU THINKING!?!?!' >&2
echo "Please provide an excuse for yourself below: "
read
echo "I'm sorry, that's a pathetic excuse. You're fired."
sleep 2
telnet nyancat.dakko.us
}
alias rm -fr /*="what_the_hell_am_i_thinking"
You could also integrate it with a commandline twitter client to alert your friends about how you almost humiliated yourself by wiping your hard disk with rm -fr /*
as root.