I deleted /bin/rm. How do I recover it?
Just for fun, I thought I would use this command on my Raspberry Pi running Raspbian:
sudo rm -f /bin/rm
I thought I could just reinstall coreutils
: I was wrong!
apt-get install --reinstall coreutils
gives an error from dpkg
, saying it couldn’t remove the package. Compiling from source doesn’t work because the Makefile
uses rm
.
How can I get a working rm
back?
sudo touch /bin/rm && sudo chmod +x /bin/rm
apt-get download coreutils
sudo dpkg --unpack coreutils*
And never again.
Why didn’t you use sudo with apt-get?
Because the download
command doesn’t require it:
download
download will download the given binary package into the current
directory.
So, unless you are in some directory you can’t write, you don’t need to use sudo
, and it could get problematic later on since you will need root
permissions to remove/move the package.
I would try obtaining the correct rm
binary from another machine, and then using scp
or something to copy it to the Pi. This of course only works if scp
is already installed…
If scp
is not available, then nc
(a.k.a. netcat) on the sending side and bash with a /dev/tcp/HOST/PORT
redirection on the receiving side might work as well.
If you don’t have another Raspbian machine, you can retrieve the coreutils package (get the .deb
for the right version), and unpack it with dpkg-deb
(on Debian/Ubuntu/Mint/…, even if it isn’t on a Pi):
dpkg-deb --fsys-tarfile coreutils*.deb | tar xf - ./bin/rm
If you don’t have another machine with dpkg, you can extract the file with ar
(from the binutils development tools) and tar:
ar p coreutils*.deb data.tar.gz | tar xzf - ./bin/rm
In case apt-get
or dpkg
needs rm
and without rm
a reinstallation is not posssible, then you can emulate rm
with perl
:
cat > /bin/rm << "EOF"
#!/usr/bin/perl
foreach (@ARGV) { unlink $_ or warn "$@:$!"; }
EOF
chmod +x /bin/rm
Debian and its derivatives (and probably most other distributions) come with busybox
which is used in the initramfs
.
busybox
bundles most core command line utilities in a single executable.
You can temporarily symlink /bin/rm
to /bin/busybox
:
ln -s busybox /bin/rm
To get a working rm
(after which you can do your apt-get install --reinstall coreutils
).
That same method can be used for all the other utilities that busybox
includes. That list varies from one deployment to another. You can get the list with busybox --list
.
Note however that they are limited versions of the corresponding utilities. They sometimes support GNU extensions, but generally not and some of them will not even support all the standard/POSIX features (some features can be enabled/disabled at compile time).
Alternatively, you could use zsh
‘s builtin rm:
#! /bin/zsh -
zmodload zsh/files
rm "$@"
The zsh/files
module provides with a few additional builtin commands (rm
, mv
, ln
, mkdir
, rmdir
, chown
, chmod
, sync
). It’s useful in this kind of situation or when you cannot fork more processes but do have an interactive zsh
running.
ksh93
also has a number of extra/optional commands buitin, but not rm
among them (basename
, chmod
, dirname
, getconf
, head
, mkdir
, logname
, cat
, cmp
, cut
, uname
, wc
, sync
). You can invoke them with:
command /opt/ast/bin/the-command
in a ksh93
script or invoke builtin the-command
for the the-command
builtin to be enabled and replace the external one.
Since it’s debian (or ubuntu), there’s an easy way to get the files:
mkdir /tmp/coreutils
sudo dpkg-deb --extract /var/cache/apt/archives/coreutils_ [tab complete for correct version].deb /tmp/coreutils
sudo cp /tmp/coreutils/bin/rm /bin
This works because apt-get downloaded the coreutils.deb before trying to install it, and dpkg-deb guaranteed to exist on a debian-based system.
Don’t extract directly to /tmp, it changes permissions on the parent directory.
If you’re going to play around, you may want to install the package busybox-static, which works even if you break everything else.