如何抢救不小心 rm 掉的数据
整理项目代码的时候,本想删除原有的 git
仓库,新建一个干净的仓库,但是不小心把rm -r ./.git
按成了rm -r ./*
,然后项目文件夹就……很悲剧地直接空了。万幸的是最后还是把项目成功恢复了。
NTFS 文件格式误删除恢复
今天把项目的 RL 库改成了 ETH
开源的rls_rl
,但是在本地运行时受限于显卡显存大小,训练速度偏慢,所以我想着把项目文件传到服务器上进行训练。以往我一直都是用
git
来实现服务器和本地文件之间的同步的,所以这次我也照例打开命令行,下意识地想把原来的
git 仓库删除掉(项目是在 ETH 的 legged_gym 上进行修改的,所以有原项目的
git 仓库,这会影响到我后续查看 git
log,所以一般我都会删掉原来的仓库,新建一个新的),就在这个过程中,发生了上述的意外——我把整个项目删掉了。
由于在 Windows 下的使用习惯,我的第一反应自然是查看回收站,结果很明显,自然是没有的。那么后续的第一件事情就是把磁盘卸载掉,卸载掉磁盘后,我开始在网上搜索如何恢复 Linux 系统下误删除的文件。
对于不同的磁盘格式,Linux
上有着不同的工具可以进行进行数据恢复。我在安装系统的时候考虑到 Windows
和 Ubuntu
双系统数据读取的便利性,所有的文件分区都是NTFS
格式的,而
Ubuntu 系统可以利用 ntfs-3g
中的ntfsundelete
来实现被删除文件的恢复。如果没有安装这个包的话,对于
Ubuntu 18.04 以后的版本可以使用以下命令进行安装:
1 | $ sudo apt-get install ntfs-3g |
然后就可以使用ntfsundelete
命令来恢复文件,具体命令行参数可以参考
官方
manual。
使用ntfsundelete
,首先需要确定删除了哪些文件。在确保磁盘已经卸载了的情况下,运行
1 | sudo ntfsundelete --scan --time 1h /dev/sda3 |
其中--scan
参数表示列出所有被删除的文件信息,--time 1h
表示筛选出一个小时内删除的文件,/dev/sda3
是我删除的文件所在的分区。运行上述命令后,命令行会输出被被删除的文件的具体信息,包括
Inode,flags,age,date,time,size 和 filename,其中最关键的是
Inode。
从 Manual 来看,ntfsundelete
似乎并没有提供好用的
undelete 的筛选方法,因此需要手动设置要恢复的文件的
Inode,这里可以使用常见的文本编辑器(比如 vscode)将 Inode
提取出来,并表示成ntfsundelete
可以识别的格式(以逗号,
隔开),然后用以下命令恢复文件:
1 | sudo ntfsundelete --undelete --inodes [Inodes divided by `,`] --destination [output dir] /dev/sda3 |
恢复得到的文件会被保存到output dir
中,这次恢复得到的文件大多是文本编辑时产生的临时文件,且数量众多(因为同一个代码文件多次编辑会产生多个临时文件),名字类似于play.py~.22
,恢复的文件并不能保持原有的文件夹层次,所以进一步恢复还需要自己找出恢复文件中最新的一个版本,然后手动恢复文件夹层次。
事后:原来我早有准备
其实手动 rm 删除文件会很难恢复这件事在我刚接触 Linux
的时候就有所耳闻,在安装系统之后我也做了相关的工作,利用 bash 的 alias
把 rm 这个危险操作给它更换掉更安全的方式。知乎上有人给出了 一个 bash 的脚本
,可以直接添加到~/.bashrc
文件中,来用移动来代替rm
,具体脚本如下:
1 | alias rm=safe_rm |
这个脚本会将要删除的文件移动到{your_path}/.__trash
文件夹中,如果要恢复就可以从这里直接把文件复制回来(文件在移动过程中会被重命名,所以移动的时候需要改一下名字,但是这可比恢复数据容易的多了)。这个脚本就能实现递归删除,所以在删除文件的时候,要注意检查补全的名字(尤其是同一目录下有相同名字的文件夹时);另外,频繁使用这个命令来删除文件会导致磁盘空间越来越少,所以需要定时清理TRASH_DIR
。
实际上我这次完整数据的恢复是依赖于我的事先准备,ntfsundelete
在实际运行过程中有部分被删除文件没有能够恢复,完整的项目我直接从设定好的回收站里复制出来了。所以说,有备无患啊,尤其是rm
这种这么危险的操作,话说我好想服务器上还没有配过这个脚本,还能赶紧去弥补一下。