by Jacob Evelyn

That time I accidentally overwrote Bash… in Bash

“I know what I’m doing.”

Five years ago, a few weeks into my very first Programming Job™, I was tinkering around in bash trying to get some code to run.

I was becoming increasingly frustrated. Why wasn’t that file in my $PATH? It should have been, I felt certain of that.

But, growing more and more desperate to get something to work, I moved the file to a folder I knew was in the $PATH:

> mv ./file.whatever /bin

At least, that’s what I meant to type. In reality what I typed was:

> mv ./file.whatever /bin/bash

My employer-provided MacBook Pro yelled at me, like any good UNIX system:

mv: rename ./file.whatever to /bin/bash: Operation not permitted

And like any good programmer, I blindly added a sudo and typed in my password as quickly as I could. Stupid computer, thinking it knows better than me.

Having just unknowingly overwritten the very shell I was using, I was shocked to find my code still wouldn’t run.

“I don’t know what I’m doing but it’s okay.”

I opened a new OS X Terminal tab to try a new approach to getting my code running, and instead saw this:

> permission denied: ./file.whatever
[Process completed]

Hmm, that’s weird. Not sure why bash isn’t working, but at least it’s doing something with my file!

I switched back to my previously-open bash shell and continued trying a few commands. They still worked, of course, because the bash program was already in memory at the time I overwrote its executable.

So some Terminal tabs aren’t working, but others are. Probably ghosts in the machines.

To sort out this weird-but-definitely-probably-not-a-big-deal bash behavior I decided to do the tried-and-true cure-all: quit the app (Terminal) and open it again.

“Oh god! what have I done?”

Out of nowhere, the reality of what had happened hit me like a snowball to the face. Oh no oh no oh no I just overwrote Bash.

I no longer cared about getting my code to run. All I wanted to do was go back to the way things were.

“This is probably fixable…”

I spent a long time Googling things like “deleted bash” and “download new bash OS X” and got nowhere. I was in too much of a panic to think about using other shells — which I vaguely knew about, but didn’t realize were already installed on my machine. (And I certainly didn’t realize these shells were also usable by just changing a setting in the Terminal app. #facepalm)

Eventually, I sheepishly confessed to some coworkers what I had done and after we all had a good chuckle I got one of them to email me a copy of his bash program so I could manually move it back into the /bin folder in Finder. (Hooray for point-and-click interfaces!)

Except… Finder wouldn’t let me go to the /bin folder. OS X (that version of it, at least) hid /bin and other system folders it deemed unsafe for meddling users like me to see. Stupid computer, thinking it knows better than me.

So I Googled some more, this time for things like “view hidden folders in Finder.” I found a handful of different ways to do that, but every single one of them required me to type some magic command… into bash, which I could no longer open. Kids: if you delete your shell but have an instance of it open, don’t close it!

“OK… this is maybe fixable…”

At a loss for what to do next, I found an old internal Q&A system the company had and posted a quick description of my problem, trying to strike that balance in tone between heh what a funny but probably not uncommon situation, right everyone? and please someone anyone help me I’m panicking. The site looked like it wasn’t ever used anymore but I was hoping someone got an email when a question was posted.

Lo and behold, my Hail Mary quickly got a response: someone recommended booting from a Linux Live CD (this was back when computers had CD drives), and then from within Linux accessing my OS X file system to add bash back to its rightful place. I understood about a third of the suggestion, but went ahead anyway — what other options did I have? I found a Linux CD, did a bunch of things I didn’t understand to get it to work, and waited impatiently as the machine went through all of the myriad setup steps until — voilà! A desktop appeared!

I Googled around until I found out how to mount the OS X filesystem, and eagerly opened bash (what a good feeling!) to copy that machine’s bash executable back over to OS X… only to encounter an error message: the OS X partition was read-only from Linux. I did find out about a way to make it writable, but that required restarting back in OS X and — you guessed it — running a command in bash.

I tried a few different Linux Live CDs (each of which took about forty minutes of impatient pacing to boot), but each had the same result. Once again: if you delete your shell but have an instance of it open, don’t close it!

“What does fixable even mean anyway?”

Unsure where to go from there, I reached out to coworkers again and eureka! — someone knew of a way to navigate to any folder — even hidden ones — within Finder. All I had to do was restart in OS X again, copy the emailed bash executable to /bin, and everything would be gravy. So I shut down Linux, removed the Live CD, restarted in OS X, and…

Hmm. I couldn’t log in, because, well, the OS X login process uses a shell under the hood, and guess which shell that is?

Was I doomed to spend the rest of my career living off of Linux Live CDs? I pictured myself years in the future, a babbling hermit kept around to scare the new kids: “Don’t delete bash or you’ll end up like crazy old Jake.”

“I’ve never been happier to see an error message”

I had given up all hope, when another coworker (goodness, these people knew so much!) told me about single-user mode, a special OS X startup mode that helps you resolve login (and other) errors. Single-user mode let me boot a bare-bones, command-line version of OS X through a different shell (/bin/sh, I think). From there, it was just a matter of finding the right incantations to get the bash executable back into /bin and off of a USB drive (where I put it in another painfully slow iteration of the Linux Live CD boot).

Once that was done, I restarted the Mac and all was finally well again! Well, except that of course my code still didn’t run.