Accidentally removed /bin. How do I restore it?

I was working on a directory named bin. After I was finished, because of the ownership of bin and some files within it I accidentally ran:

sudo rm -r /bin

Instead of:

sudo rm -r bin

It seems that my hands used to add a / in front of everything I type.

How can I restore my /bin directory?

I want the same files that belong to my Ubuntu, I don’t like to copy and paste them from a live disk or another running system.

Asked By: Ravexina

||

Is it possible?

Well, most trivial and important utilities are installed in /bin, and now you lost access to all of them. In fact, if you reboot, your system will not be able to boot-up anymore.

Anyway, we are going to fix the issue and make /bin‘s contents as close as is possible to where it was. The only difference would be some symbolic links which we will fix too.


How?

First, we should chroot into your broken system, but with a minor difference! After that we will get a list of installed packages on your system which have any installed file in /bin directory, then we are going to only download the needed packages and extract the necessary files into /bin. Then we’ll be done.

For example, after chroot, we can get a list of packages which have installed files in /bin using:

dpkg --search /bin | cut -f1 -d: | tr ',' 'n'

And we can also use:

dpkg --listfiles PACKAGE-NAME | grep "^/bin/" # or awk '$0 ~ "^/bin/

to list installed files by these packages in /bin.

Then we simply create a list of all packages that are necessary to us, then download them and extract them to /bin with something like:

xargs apt download < list-packages
dpkg-deb -x PACKAGE .
mv ./bin/* /bin

However we must use a script to check all installed packages on our system, because doing it manually is just madness.

So I wrote a script which does everything we need. It finds all necessary packages for us to restore /bin, shows us the name of each package and their related files that belongs to /bin. Here is a screenshot:

Screenshot of <code>/bin</code> package list as output by my script

At the end we choose to reinstall all packages or only download and extract the necessary files to /bin (which is the recommended option):

Screenshot of options given by my script

You can grab a copy of this script or download it directly.


Lets start

chroot

Boot your system with a live disk which has same architecture as your installed Ubuntu, open a terminal and get root access:

sudo -i

Mount your root file system (for me it’s /dev/sda1):

mount /dev/sda1 /mnt

We will need connectivity to the Internet, so copy resolv.conf from live Ubuntu to your mounted root partition:

cp /etc/resolv.conf /mnt/etc/resolv.conf

Now copy the script to somewhere on the mounted partition, e.g:

cp /media/ubuntu/usb/restore-bin.sh /mnt/restore-bin.sh

or you can download it using wget, etc. like:

wget https://git.io/v9fRm -O /mnt/restore-bin.sh

Mount other necessary paths:

mount --bind /dev /mnt/dev
mount --bind /sys /mnt/sys
mount -t proc /proc /mnt/proc

And here is the minor difference: how can we chroot to a broken system when there is no /bin directory in there? Which shell should we run?

So create a temporary bin directory. e.g: named bintmp within your broken system root:

mkdir /mnt/bintmp

Then bind the live /bin into that:

mount --bind /bin /mnt/bintmp

Chroot into the system while setting the /bintmp/bash as your login shell:

chroot /mnt /bintmp/bash

Export the /bintmp as your PATH environment variable:

export PATH=/bintmp:$PATH

Give the script the executable bit:

chmod +x restore-bin.sh

Run the script:

./restore-bin.sh

Wait for the search to be completed then answer the question we saw in the screenshot. It will start to restore the /bin and we are almost done.

After it’s done, use CTRL+D to get out of chroot environment and unmount the mounted paths:

umount -R /mnt

Reboot the system.

Restoring the links within /bin

Now almost all of files within /bin directory are back, except around 5 symbolic links which are managed by update-alternatives.

In your running system, run:

sudo update-alternatives --all

It asks you some questions; you can simply press ENTER to accept them all.

And now we are done.

Answered By: Ravexina

If your current system still has a running shell and internet access, this can be done using tools existing elsewhere on the system. I’m assuming you only deleted /bin. /bin of course has the most convenient utility that you could use in such a situation (busybox), but without that, we’ll have to get a little creative.


Since you already have a running shell, and since sudo is in /usr/bin, let’s get ourselves a running root shell before we do further damage. But /bin/bash and most other shells are gone! Luckily, Linux still has an in-memory copy of the shell you’re using. So:

sudo /proc/$$/exe

Strictly speaking we don’t need a root shell for much of what follows. But anyway.

Now, dpkg still works, at least for finding which packages have files in /bin:

dpkg -S /bin

We can use awk to process it and get the package names, and xargs and apt-get to download the packages (all in /usr/bin). If you have a temporary directory that you can use, cd there, because your current directory is going to get a bit messy:

dpkg -S /bin | awk -F '[, :]' '{NF--}1' | xargs apt-get download

Now, the biggest problem we have is that /bin/tar is missing, and without it, dpkg can’t extract the archives. We can get two-thirds of the way there, because:

  1. .deb files are actually ar archives (again in /usr/bin):

    ar x tar_*.deb
    
  2. Consisting of two .tar.* archives, data and control:

    $ echo *.tar.*
    control.tar.gz data.tar.xz
    
  3. While the gzip utilities are in /bin, unxz is in /usr/bin:

    unxz data.tar.xz
    

Now we have a data.tar file without tar to extract tar from it.

Python to the rescue! This is where sudo is really needed:

$ sudo python -c 'import tarfile; tarfile.open("data.tar").extractall("/")'
$ echo /bin/*
/bin/tar

Now we can use dpkg to extract the remaining deb files to get a reasonably complete /bin:

for i in *.deb; do dpkg-deb -x "$i" /; done

However, we should still do a proper installation of the deb files, so that symlinks etc. that would be created by packages are re-created:

sudo apt install --reinstall ./*.deb

Or:

sudo dpkg -i *.deb
sudo apt-get install -f

Notes:

  1. We can’t use Python 2 to directly extract the data.tar.xz file, since Python 2 only supports gzip and bzip2 compression. Python 3, however, does support it, so you can use Python 3 directly without unxz:

    sudo python3 -c 'import tarfile; tarfile.open("data.tar.xz").extractall("/")'
    
  2. After getting back /bin/tar, you still need to extract some of the deb files before you can use apt-get: the shells, coreutils, etc. Easier to just extract all of them and re-install later.
Answered By: muru

You could temporarily put files from a live CD or another system into your /bin to make your system usable, then replace them with files from your Ubuntu installation by running apt-get install --reinstall for packages which have stuff in /bin.

Answered By: Dmitry Grigoryev

Some additions to this excellent answer, after I encountered this issue (along with deleting /boot, /etc, /lib and /lib64):

  • chroot requires /lib and /lib64 to be present; otherwise you will get the following error:
    failed to run command ‘/bin/bash’: No such file or directory
    I copied these from the LiveCD OS and didn’t have any problems restoring. YMMV depending on the packages you have installed on the system
  • I cannot edit the answer referenced above, but there is a typo:
    cp /etc/resolv.conf /mnt/etc/resolv.cof
    should be
    cp /etc/resolv.conf /mnt/etc/resolv.conf
  • /boot can easily be restored using grub tools. See here.
  • As this answer recommends, apt install --reinstall <package> is a great way to restore missing files in /bin, /lib and /lib64.
    • Some packages that required reinstallation: libaio1, mysql-server, openvpn, vsftpd

Note to self:
rm -rf folder /* is not the same as rm -rf folder/*

Answered By: mrtumnus
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.