不小心删除了/ bin。如何还原?


91

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

sudo rm -r /bin

代替:

sudo rm -r bin

似乎我的手经常/在输入的所有内容前添加一个。

如何还原/bin目录?

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


3
难道不是/bin在Ubuntu上/usr/bin这些天的符号链接吗?因此,您所需要做的就是放回符号链接?
Muzer '17

3
@Muzer我正在运行16.04,并且/bin不是指向/usr/bin此处的符号链接,我认为这与FHS。此外,如果我们检查一个简单的包像coreutilszesty (这里)。我们可以看到很多东西将被安装在的/bin旁边/usr/bin,但是它仍然可以是一个链接,我不知道。
Ravexina '17

2
@Ravexina Arch Linux已经将/ bin符号链接到/ usr / bin
Dmitry Kudriavtsev

1
我以为人们会意识到这是一个虚假的情况,我实际上并没有删除我的内容/bin,我考虑了可能发生在其他任何人身上的事情(基于我回答的另一个问题),然后我写了一条指令分享我的知识和其他人:),尽管我感谢所有评论,但它们也对其他阅读此问题的人有所帮助。谢谢大家;)
Ravexina

1
我已经习惯了每当我使用“ rm -r”命令或任何其他可能引起严重后果的命令时,我都会键入该命令,然后至少在敲击之前将手从键盘上移开约3秒钟。输入。这使我有机会查看一下,并确保正确键入了所有内容,并且知道它将执行我打算做的事情。在极少数情况下,在该暂停期间,我确实决定需要删除该命令-并非总是因为这是错误的命令,而是有时因为我需要首先进行一些验证。
2017年

Answers:


180

可能吗?

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

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


怎么样?

首先,我们应该chroot进入您已损坏的系统,但要稍有不同!之后,我们将获得系统上已安装软件包的列表,这些软件包的/bin目录中有任何已安装的文件,然后我们将仅下载所需的软件包并将所需的文件提取到中/bin。然后,我们将完成。

例如,在之后chroot,我们可以获取/bin使用以下命令安装了软件包的软件包列表:

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

我们还可以使用:

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

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

然后,我们只需创建一个对我们必需的所有软件包的列表,然后下载它们并将它们解压缩到以下位置/bin

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

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

因此,我编写了一个脚本,该脚本可以完成我们需要的所有操作。它会找到所有需要还原的软件包,并向我们/bin显示每个软件包的名称及其所属的相关文件/bin。这是屏幕截图:

我的脚本输出的<code> / bin </ code>软件包列表的屏幕快照

最后,我们选择重新安装所有软件包,或仅下载所需的文件并将其解压缩到/bin(建议的选项):

我的脚本提供的选项的屏幕截图

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


开始吧

chroot

使用具有与所安装的Ubuntu相同的体系结构的活动磁盘来引导系统,打开终端并获得root访问权限:

sudo -i

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

mount /dev/sda1 /mnt

我们将需要与Internet的连接,因此请resolv.conf从实时Ubuntu 复制到已安装的根分区:

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

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

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

或者,您也可以使用进行下载wget,例如:

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

挂载其他必要的路径:

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

这是次要的区别chroot/bin目录中没有目录时,如何处理损坏的系统?我们应该运行哪个外壳?

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

mkdir /mnt/bintmp

然后将live绑定/bin到其中:

mount --bind /bin /mnt/bintmp

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

chroot /mnt /bintmp/bash

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

export PATH=/bintmp:$PATH

给脚本可执行位:

chmod +x restore-bin.sh

运行脚本:

./restore-bin.sh

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

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

umount -R /mnt

重新启动系统。

恢复其中的链接 /bin

现在,/bin目录中的几乎所有文件都返回了,除了大约5个由所管理的符号链接update-alternatives

在运行的系统中,运行:

sudo update-alternatives --all

它问你一些问题;您只需按一下ENTER即可接受所有内容。

现在我们完成了。


30
毫无疑问,这是我在Ask Ubuntu上看到的最佳答案。知道OP处在不方便的情况下,您要去做很多工作,真是太好了。
Nonny Moose

15
哦,等一下;博士。我应该意识到你做到了。
诺妮穆斯

这真太了不起了。我喜欢SE设计如何完全不给出任何暗示,这是一个自我回答的问题。
佩德罗

5
@Hamsteriffic:看到包含回答者姓名(签名)的矩形:背景较暗,不是由OP发布的帖子就没有。这适用于评论,答案和问题。
Ruslan

27

如果您当前的系统仍然具有运行中的外壳程序和Internet访问权限,则可以使用系统上其他位置存在的工具来完成此操作。我假设您只是删除了/bin/bin当然,在这种情况下(busybox),您可以使用最方便的实用程序,但是如果没有这种实用程序,我们将不得不有所创新。


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

sudo /proc/$$/exe

严格来说,我们不需要root shell。但无论如何。

现在,它dpkg仍然有效,至少可以找到以下文件中的文件/bin

dpkg -S /bin

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

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

现在,我们面临的最大问题/bin/tar是丢失了,没有它,dpkg就无法提取档案。我们可以到达那里的三分之二,因为:

  1. .deb文件实际上是ar归档文件(同样是/usr/bin):

    ar x tar_*.deb
    
  2. 包含两个.tar.*档案,data以及control

    $ echo *.tar.*
    control.tar.gz data.tar.xz
    
  3. 当gzip实用程序位于时/binunxz位于/usr/bin

    unxz data.tar.xz
    

现在我们有了一个data.tar文件,没有tar要提取的文件tar

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

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

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

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

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

sudo apt install --reinstall ./*.deb

要么:

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

笔记:

  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("/")'
    
  2. 恢复后/bin/tar,您仍然需要解压缩一些deb文件,然后才能使用apt-get:shell,coreutils等。更容易地将它们全部解压缩并在以后重新安装。

我没有测试它,但是我几乎完全读了它,真是太棒了,实际上我试图在内存中找到bash的副本,我进行了一些搜索,没有发现任何有趣的东西,当我看到tar是不在/usr/bin,我说了与chroot一起去的一切……太棒了。
Ravexina

1
一个问题,不是/proc/$$/exe链接/bin/bash吗?/bin移除后如何运作?(它正在工作,但是如何工作),我认为这应该是一个断开的链接……这就是为什么我放弃了这个想法。
Ravexina

3
@Ravexina没有得到完整的答案,但是:/ proc / <pid> / exe符号链接与普通符号链接有何不同?
muru

1
PATH = / usr / lib / klibc / bin:$ PATH将把cat和sh放回您的路径
Joshua

@Joshua和他们每个人都静态链接!真好!
muru

7

您可以暂时将实时CD或其他系统中的文件放入/bin系统中,以使系统可用,然后运行运行apt-get install --reinstall中包含内容的软件包,将它们替换为Ubuntu安装中的文件/bin


这就是我要做的。如果版本不相同,则实时DVD的版本号几乎相同。如果我有光盘或USB Live版本,我可以将它们进行比较并发布一个像您一样的答案。如果OP首先从不删除/ bin,那么该线程更是一个理论,这是有可能的,因为他很可能在与问题同时写答案的同时。还是非常不错的思想实验和出色的写作风格。
WinEunuuchs2Unix

我建议编辑此答案以将其扩展为有关如何执行此操作的特定详细信息。(另请参阅“我如何编写一个好的答案?”,以获取有关在AskUbuntu上认为最有价值的答案的一般建议。)
David Foerster

1

在遇到此问题后(除了删除,和),还添加了一些出色的答案/boot/etc/lib/lib64

  • chroot要求/lib/lib64存在;否则,您将收到以下错误:
    failed to run command ‘/bin/bash’: No such file or directory
    我从LiveCD OS复制了这些文件,并且在恢复时没有任何问题。YMMV取决于您在系统上安装的软件包
  • 我无法编辑以上引用的答案,但是有一个错字:
    cp /etc/resolv.conf /mnt/etc/resolv.cof
    应该是
    cp /etc/resolv.conf /mnt/etc/resolv.conf
  • /boot可以使用grub工具轻松恢复。看这里
  • 由于这个答案建议,apt install --reinstall <package>在恢复丢失的文件一个伟大的方式/bin/lib/lib64
    • ,需要重新安装一些软件包:libaio1mysql-serveropenvpnvsftpd

自我注意:
rm -rf folder /*rm -rf folder/*

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.