Unix Recovery Legend (1986)
ee.ryerson.ca
ee.ryerson.ca
A long time ago, in a job far, far away, I was a lowly CAD Operator making technical drawings of electrical diagrams and switchgear enclosure plans. This was on Tektronix terminals each attached to their own Tektronix servers (which as I recall ran BSD at first then switched to SVr4)
A fellow lowly cad operator decided to try out the "rm -rf" command (at that time we each had superuser access to our servers - innocent days) on his server. In those days you could hear the hard drive access each sector, and so it was I heard the faint but distinctive click-click-click of the read/write head slowly but surely going down the sectors as the rm command took hold, followed by my cow-orker's face gradually but increasingly turning white, going through to green, as he realised that a major project's 2 months of un-backed up CAD drawings were gurgling down the virtual drain (again innocent times - no backups).
Being a bit of an unofficial Unix Nerd (I whiled away my spare times there learning how these boxes worked), I had the chance to show my knowledge, explain what went wrong, and how we could prevent this in the future, resulting in - after 2 weeks of overtime for all to re-draw and catch up with the 2 months of lost project work - removal of root access to the systems to all but myself and other key personnel, and a tape backup system with a rigidly kept backup schedule, and subsequent no loss of data after that.
I eventually became in charge of the CAD dept, and years later ended up as manager of IT at a different company, and now run my own IT company ;)
rm -f *.c
instead of: rm -f *.o
I then typed: make
I saw tons of missing files and in literally maybe 200ms I hit the reset button on the machines' console! I happened to be sitting there the only thing I could think is these blocks are still in the free list and maybe even the disk didn't sync yet (did I mention this was Xenix, and 1985?).I rebooted the machine from a 8" floppy that had a copy of fsdb(ADM) and stated sniffing around. Sadly the file changes had been sync'd but I found my code on the free list in the filesystem! I then wrote a C program to dump the free blocks and proceeded to reassemble it into the original C file I needed to recoup my 12 hours of work. Luckily most of the files where the same from a prior backup just one file had a ton of changes from that session. It took me a couple hours to get perfect but it was better then re-writing everything I'd done in the past 12 hours.
Needless to say I then added a "make clean" target and I got much better at backing up my code every couple of hours instead of being a code zombie and waking up 12 hours later without backups!
With today's modern filesystems I have no clue how you could pull off a hat trick like this but that was then and I used the tools I had at my disposal to recover from my own blurry eyed mistake.
A friend of mine once said to me:
It's not how bad you mess up it's how well you recover.
And you're a professional at recovery.
I'm still not sure if that was a compliment or an insult...cd /var/lib/$application/cache
find -type f -delete
But that application was actually load-balanced on a second machine; we didn't need to change the configuration there, but still had to delete the caches. So he ssh'd (as root) right into it, and copy&pasted the 'find -type f -delete' right away, and pressed enter while I cried NOOOOOOO. Too late he realized he didn't change the directory first.
He was about to log out, and instead ssh into the backup server to recover the lost files, but I stopped him from logging out - the previous operation had erased the .ssh/authorized_keys file from /root.
In the end, no harm was done, the backups were only 8 hours, and nobody noticed any interruption.
We once had a server running a memory-only cache lose its hard-drive. It puttered along for weeks, still serving from memory, before someone got around to replacing it.
I had a genius intern. Straight out of high school, his understanding of asynchronous design put plenty of my peers to shame. Course, his unix experience, especially permissions in this case, was a bit light.
I decided to use OSX's iChat to share my screen with him. As you know, iChat used to allow full control of the local machine to the remote viewer. My bright-eyed genius intern realized this:
Oh cool! I can move your mouse!
...he says, as he starts clicking around... Can I type?!
...and he types "rm -rf /" in my open terminal.In panic, I smashed every key on my keyboard, fortunately scoring a CONTROL+C relatively quickly. I hoped the damage was minimal, mostly praying it did not touch my home directory. I watched as every application I tried to open failed to start...
Every application I had installed, up to somewhere near X in the alphabet, had been deleted without prejudice before I managed to kill the command. Fortunately my home directory was safe; thank you "/Users" on OSX.
My intern's response was:
That command won't do anything, I didn't sudo it!
That's the day I setup Time Machine on that system. rm -rf $2Applications/iTunes.app 2< /dev/null
$2 held the path to the drive containing the copy of iTunes to be deleted. If the name of that drive began with a space, chaos ensued....I had lots of dot-directories in /tmp and my disk didn't have a lot of space left. So I typed in
rm -rf .*
thinking that I was very smart, and would save time by not having to remove each dot-directory separately.After a while, I wondered why it was taking so long and discovered I had very little of my root filesystem left, so I was forced to do a complete reinstall.
Needless to say, I always do my day-to-day work now as a lowly common user, and NOT as root.
rm -rf "$foo/$bar"
- when the variables were undefined due to a bug in the script. Fortunately I was not running it as root.
set -u
in every script i've written since i did exactly the same thing.
Ofc. unset (empty) variables "rm -rf ${variable}/" ... I guess paths are given without a slash at the end (also for that reason).
But also other commands: "hostname", if you type "hostname help" then your new hostname is set to "help". For us that means a full rebuild/reinstallation of the machine is necessary.
This surely has been discussed before, but why not (again): Let me know of your horror stories, if you like.
What a fun day that was....
There is no trash can in my Unix, deleted is gone forever.
A move (mv) or copy (cp) just overwrites files with the same name (as default)
Right clicking (&executing everything (every line) that just got pasted from the current clipboard/copy-buffer)
Having your shell expand * is just asking for trouble; on most systems you'll have no problems creating more entries in a directory than you can specify arguments on the command line, so rm -rf * will not work from 'somewhere' but rm -rf somewhere should still work fine.
set -o nounset
set -o pipefail
set -o errexit
set -o xtrace
I added them to all my scripts, and I also added all except errexit to ~/.bashrc
The first one would save you from unset variables.
Then using the killall command on a Solaris box, which just happened to be running the company's Oracle database...
Cue the support line phone ringing off its hook.
Cue BOFH Excuse : "Hmm it appears the server running the database has crashed. We're rebooting it now", etc etc.
Lesson learned : killall on a Sun/Solaris box behaves VERY differently from the killall on Linux :D
That's what taught me the importance of backups.
What the hell? Why not just change it back?
Here is another one: I once shut down a server because I wanted to know how to shutdown & reboot. I typed "shutdown -h" (I thought that would display help-pages :)
It was the option to "halt" immediately.
We needed to open a ticket to start the machine up again.
It might get really annoying really fast though and only iron discipline will prevent you from forgetting to chattr +i something back after chattr -i to do an upgrade. And if you have such a good discipline, you're extremely unlikely to ever do a rm -rf /*.
It would be nice if you could have some hook in the package manager so you could write something to automatically chattr -i relevant files and then chattr +i them back. And a vim macro to do the same when you save a file in /etc.
Reminds me of the "most stupid thing" I ever typed into Terminal.app. I somehow managed to create a subdirectory named "~", and decided it was a good idea to do this:
rm -rf ~
It took me about 5 seconds to realize the command should have returned immediately, and frantically press Ctrl-c. But that was all that was needed to ruin two week worth of code.If you want to try a fun little experiment, type this command into your colleague's shell and see what happens (and how long it takes):
mkdir ./~> mkdir ./~
$ time mkdir ./~
real 0m0.007s
user 0m0.000s
sys 0m0.004s
I don't get it. What's fun about this experiment?So, when i delete a directory, whenever possible, i use the rmdir command. rmdir refuses to delete a directory which isn't empty. It's a really handy safety check. If a colleague dropped a tilde directory on me, the process would go:
Well, i'll just delete that.
$ rmdir ~
rmdir: /home/twic: Directory not empty
Oh bugger, of course. Better quote it.' $ rmdir '~'
Right, now i will proceed to give my colleague a Chinese burn. rm -rf ~
It took me about 5 seconds to realize the command should have returned immediately, and frantically press Ctrl-c. But that was all that was needed to ruin two week worth of code.If you want to try a fun little experiment, type this command into your colleague's shell and see what happens (and how long it takes):
mkdir ./~I have a coworker who never does this and it drives me crazy. He just blindly trusts his first attempt. And yes, he has accidentally deleted stuff, but thankfully nothing that was irrecoverable... so far.
For Linux there's a suite called "trash-cli" (on Ubuntu the binary is called "trash-put" so you will probably want to set up an alias). I guess there's something similar for OSX?
Yet, I've lost interest since I got a nice backup routine.
# alias rm
alias rm='rm -i'
It helps to prevent some stupidity, sometimes. Better than nothing.
The article should have [2006] in the title though.
An argument could be made that [1986] would be more accurate.