不小心删除了 /bin。我该如何恢复?

Rav*_*ina 97 command-line restore

我正在处理一个名为bin. 完成后,由于所有权bin和其中的一些文件,我不小心运行了:

sudo rm -r /bin
Run Code Online (Sandbox Code Playgroud)

代替:

sudo rm -r bin
Run Code Online (Sandbox Code Playgroud)

似乎我的手过去常常/在我键入的所有内容前面添加一个。

我怎样才能恢复我的 /bin目录?

我想要属于我的 Ubuntu 的相同文件,我不喜欢从活动磁盘或其他正在运行的系统中复制和粘贴它们。

Rav*_*ina 186

是否可以?

好吧,大多数琐碎和重要的实用程序都安装在 中/bin,现在您无法访问所有这些实用程序。事实上,如果您重新启动,您的系统将无法再启动。

无论如何,我们将解决这个问题并使/bin的内容尽可能接近它所在的位置。唯一的区别是一些我们也将修复的符号链接。


如何?

首先,我们应该chroot进入你的破系统,但有细微的差别!之后,我们将获得系统上已安装软件包的列表,其中/bin目录中有任何已安装文件,然后我们将只下载所需的软件包并将必要的文件解压缩到/bin. 那我们就完了。

例如,在 之后chroot,我们可以获取已安装文件的软件包列表/bin

dpkg --search /bin | cut -f1 -d: | tr ',' '\n'
Run Code Online (Sandbox Code Playgroud)

我们还可以使用:

dpkg --listfiles PACKAGE-NAME | grep "^/bin/" # or awk '$0 ~ "^/bin/
Run Code Online (Sandbox Code Playgroud)

列出这些包中安装的文件/bin

然后我们简单地创建一个我们需要的所有包的列表,然后下载它们并将它们解压缩到/bin

xargs apt download < list-packages
dpkg-deb -x PACKAGE .
mv ./bin/* /bin
Run Code Online (Sandbox Code Playgroud)

但是,我们必须使用脚本来检查系统上所有已安装的软件包,因为手动执行此操作简直是疯了。

所以我写了一个脚本来完成我们需要的一切。它为我们找到所有需要恢复的包/bin,向我们显示每个包的名称及其所属的相关文件/bin。这是一个屏幕截图:

我的脚本输出的 <code>/bin</code> 包列表的屏幕截图

最后,我们选择重新安装所有软件包或仅将必要的文件下载并解压缩到/bin(这是推荐的选项):

我的脚本给出的选项的屏幕截图

您可以获取此脚本的副本直接下载


开始吧

chroot

使用与安装的 Ubuntu 具有相同架构的实时磁盘启动系统,打开终端并获得 root 访问权限:

sudo -i
Run Code Online (Sandbox Code Playgroud)

挂载你的root文件系统(对我来说是/dev/sda1):

mount /dev/sda1 /mnt
Run Code Online (Sandbox Code Playgroud)

我们需要连接到互联网,所以resolv.conf从 live Ubuntu复制到你挂载的根分区:

cp /etc/resolv.conf /mnt/etc/resolv.conf
Run Code Online (Sandbox Code Playgroud)

现在将脚本复制到已安装分区上的某个位置,例如:

cp /media/ubuntu/usb/restore-bin.sh /mnt/restore-bin.sh
Run Code Online (Sandbox Code Playgroud)

或者您可以使用wget等下载它,例如:

wget https://git.io/v9fRm -O /mnt/restore-bin.sh
Run Code Online (Sandbox Code Playgroud)

挂载其他必要的路径:

mount --bind /dev /mnt/dev
mount --bind /sys /mnt/sys
mount -t proc /proc /mnt/proc
Run Code Online (Sandbox Code Playgroud)

这是一个细微的区别chroot当那里没有/bin目录时,我们如何才能到一个损坏的系统?我们应该运行哪个shell?

所以创建一个临时的bin目录。例如:bintmp在您损坏的系统根目录中命名:

mkdir /mnt/bintmp
Run Code Online (Sandbox Code Playgroud)

然后将 live 绑定/bin到:

mount --bind /bin /mnt/bintmp
Run Code Online (Sandbox Code Playgroud)

将 chroot 设置/bintmp/bash为登录 shell时进入系统:

chroot /mnt /bintmp/bash
Run Code Online (Sandbox Code Playgroud)

将 导出/bintmp为您的PATH环境变量:

export PATH=/bintmp:$PATH
Run Code Online (Sandbox Code Playgroud)

给脚本可执行位:

chmod +x restore-bin.sh
Run Code Online (Sandbox Code Playgroud)

运行脚本:

./restore-bin.sh
Run Code Online (Sandbox Code Playgroud)

等待搜索完成,然后回答我们在屏幕截图中看到的问题。它将开始恢复/bin,我们几乎完成了。

完成后,使用CTRL+D退出chroot环境并卸载已安装的路径:

umount -R /mnt
Run Code Online (Sandbox Code Playgroud)

重新启动系统。

恢复里面的链接 /bin

现在/bin目录中的几乎所有文件都回来了,除了大约 5 个由update-alternatives.

在您正在运行的系统中,运行:

sudo update-alternatives --all
Run Code Online (Sandbox Code Playgroud)

它会问你一些问题;您只需按ENTER即可全部接受。

现在我们完成了。

  • 毫无疑问,这是我在 Ask Ubuntu 上看到的最佳答案。知道 OP 处于不便的情况下,您还从事如此多的工作,真是太好了。 (33认同)
  • 哦,等一下;博士。我应该意识到你这样做了。 (17认同)
  • @Hamsteriffic 确实如此:查看包含回答者姓名(签名)的矩形:它的背景较暗,而不是 OP 发布的帖子则没有。这适用于评论、回答和问题。 (6认同)

mur*_*uru 30

如果您当前的系统仍然有一个正在运行的 shell 和互联网访问,这可以使用系统上其他地方现有的工具来完成。我假设你只删除了/bin. /bin当然有您可以在这种情况下使用的最方便的实用程序(busybox),但没有它,我们将不得不有点创意。


既然您已经有一个正在运行的 shell,并且sudo在 中/usr/bin,那么在我们进一步破坏之前让我们自己获得一个正在运行的 root shell。但是/bin/bash,大多数其他贝壳都不见了!幸运的是,Linux 仍然有您正在使用的 shell 的内存副本。所以:

sudo /proc/$$/exe
Run Code Online (Sandbox Code Playgroud)

严格来说,接下来的大部分内容我们不需要 root shell。但无论如何。

现在,dpkg仍然有效,至少用于查找哪些包中有文件/bin

dpkg -S /bin
Run Code Online (Sandbox Code Playgroud)

我们可以使用awk处理,并得到了包名,并xargsapt-get下载包(所有/usr/bin)。如果您有一个可以使用的临时目录,那么cd在那里,因为您的当前目录会变得有点乱:

dpkg -S /bin | awk -F '[, :]' '{NF--}1' | xargs apt-get download
Run Code Online (Sandbox Code Playgroud)

现在,我们遇到的最大问题/bin/tar是缺少它,dpkg如果没有它,就无法提取档案。我们可以做到三分之二,因为:

  1. .deb文件实际上是ar档案(再次在/usr/bin):

    ar x tar_*.deb
    
    Run Code Online (Sandbox Code Playgroud)
  2. 由两个.tar.*档案组成,data以及control

    $ echo *.tar.*
    control.tar.gz data.tar.xz
    
    Run Code Online (Sandbox Code Playgroud)
  3. 当 gzip 实用程序在/bin,unxz中时/usr/bin

    unxz data.tar.xz
    
    Run Code Online (Sandbox Code Playgroud)

现在我们有一个data.tar文件,无需tar从中提取tar

Python 来救援!这是sudo真正需要的地方:

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

现在我们可以使用dpkg提取剩余的 deb 文件来获得一个合理完整的/bin

for i in *.deb; do dpkg-deb -x "$i" /; done
Run Code Online (Sandbox Code Playgroud)

但是,我们仍然应该正确安装 deb 文件,以便重新创建由包创建的符号链接等:

sudo apt install --reinstall ./*.deb
Run Code Online (Sandbox Code Playgroud)

或者:

sudo dpkg -i *.deb
sudo apt-get install -f
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 我们不能使用 Python 2 直接提取data.tar.xz文件,因为 Python 2 只支持 gzip 和 bzip2 压缩。但是,Python 3 确实支持它,因此您可以直接使用 Python 3,而无需unxz

    sudo python3 -c 'import tarfile; tarfile.open("data.tar.xz").extractall("/")'
    
    Run Code Online (Sandbox Code Playgroud)
  2. 回来后/bin/tar,您仍然需要提取一些 deb 文件才能使用apt-get:shell、coreutils 等。更容易提取所有这些文件并稍后重新安装。

  • @Ravexina 没有得到完整的答案,但是:[/proc/&lt;pid&gt;/exe 符号链接与普通符号链接有何不同?](https://unix.stackexchange.com/q/197854/70524) (3认同)

Dmi*_*yev 7

你可以暂时把文件从Live CD或者其他系统到您/bin,使您的系统中使用,然后通过运行与你的Ubuntu的安装文件替换它们apt-get install --reinstall对于具有东西在包/bin