损坏的XFS并没有办法xfs_repair

我的一个托pipe服务器有一些XFS问题。 最后一次崩溃后,我的一些RRD文件夹被损坏。

例如(对不起,这是法语):

# rm * rm: impossible de supprimer « create_rrd.sh »: La structure a besoin d'un nettoyage rm: impossible de supprimer « old »: est un dossier rm: impossible de supprimer « tcgraph.log »: La structure a besoin d'un nettoyage rm: impossible de supprimer « tcgraph.rrd »: La structure a besoin d'un nettoyage 

正常的做法是用单用户重新启动系统,或使用live cd,然后在/ dev / sda上运行xfs_repair。 不幸的是(这太容易了),托pipe公司提供了一个选项来重新启动一个活的光盘,这是行不通的。 而访问数据中心不是一个select。

看来我根本不能碰到inode,每次都得到“结构需要清理”的信息。

所以,问题是:有没有人知道用手修复/修复XFS文件系统的方法? 任何低级别的XFS操作工具,可以帮助?

最简洁的答案是不。

更长的回答是,尝试将所有内容复制到tmpfs虚拟磁盘,切换到该虚拟磁盘,然后卸载硬盘文件系统,并在修复驱动器文件系统时从ram完全运行,将会非常有趣

我不是第一个想到这个,我发现这个线程,但没有关于该计划是否实际工作的信息。 由于它的目的是擦拭驱动器,所以他们没有打扰它的卸载。

要做到这一点,创build一个目录并mount -t tmpfs none /some/directory ,然后开始填充系统的重要部分(sshd,mount,umount,xfs工具,shell以及所有需要的库运行它,可能所有的/ etc可以肯定,最后init … chroot监狱创build脚本将在这里帮助,因为将有大约4GB的内存。挂载一个proc的副本,如果你使用的是devfs,使用/ etc / ssh / sshd_config的副本,设置sshd以启动另一个端口。chroot到你的ramdisk,确保一切正常,没有丢失的库,然后启动sshd (在备用端口上),这样它就被chroot了,检查你是否可以ssh进入(这可能需要复制你的/ home目录到那里)(并打开任何防火墙上的端口)。

现在,魔法开始了:你需要find一个名为pivot_root的工具来代替对tmpfs的chroot。 它唯一的目的是调用pivot_root() 。 它在Debian的util-linux上。 pivot_root()的目的本质上是一次性彻底地处理每个进程 。 最初用于从initrd ramdisk映像移动到实际驱动器,如果这样做,您将从实际驱动器移动到ramdisk映像。 所以,假设你做了mkdir /mnt/tmpfs; mount -t tmpfs none /mnt/tmpfs mkdir /mnt/tmpfs; mount -t tmpfs none /mnt/tmpfs拷贝好你需要的所有内容之后,下一步是mkdir /mnt/tmpfs/oldroot; pivot_root /mnt/tmpfs /oldroot mkdir /mnt/tmpfs/oldroot; pivot_root /mnt/tmpfs /oldroot (如果空间不足,请复制东西,卸载/ mnt / tmpfs并重新挂载,这次使用-o size=...因为默认值只允许一半的内存。

最后一步是取/旧根据卸载。 你需要卸载/旧的/ sysfs / oldroot / proc等(检查/ proc / mounts)。 如果你仍然“文件系统正忙”,你可以尝试强制它,或者至less通过查看ls -l /proc/*/cwd /proc/*/fd/ | grep /oldroot/ ls -l /proc/*/cwd /proc/*/fd/ | grep /oldroot/并杀死所有依然指向它的东西(这可能包括没有被chroot的ssh服务器。确保你在开始查杀之前以sshd的方式login)。 显然不要kill进程1(init)。 如果在运行init的时候不能强制umount,你需要使用chroot /oldroot /sbin/telinit u22 =你当前运行的是runlevel,否则init可能会 chroot /oldroot /sbin/telinit u2 一切,然后重新启动并重新启动 )通过运行你在虚拟硬盘上的“新”init来“升级”。 你需要把它拷贝到/ oldroot,以便使用/ oldroot / dev / initctl(ramdisk / dev / initctl是不一样的)(注意,telinit将使用[/ oldroot] / dev / initctl与现有的init_process进行对话,这个进程是pivot_rooted到ramdisk,所以init启动的init将在ramdisk上,而不是/ oldroot)。

我不打算在这里的生产服务器上尝试。 也许我会在本周末在家尝试。