删除数据的两种场景:
- 场景一:在执行 rm -rf 删除文件时,该文件正在被进程使用
对于进程正在使用文件的场景,数据可以恢复是由因为 Linux 里,每个文件都有2个link 计数器: i_count和i_nlink
i_count:当一个文件被一个进程引用时,它的数值会加1也就是说它记录的是文件被进程引用的次数
i_nlink:记录文件产生硬链接的个数
Linux 系统只有在两个数值都清零的时候文件才被系统认为是删除的,假设此时删除文件有进程在使用那么(i_count)数值不为 0
- 场景二:这个文件并没有被其他进程所使用,而被误删除
将没有被进程使用的文件误删除,此时i_count和i_nlink都为0,inode 连接信息已经被删除了,我们就需要通存放文件的 block 单元,做数据块的数据找回
inode:用于存放文件的相关元数据,它的元数据里会有一个类似于索引的值,能够索引到后面具体存放数据的 block 单元
block:是一个数据块,用来实际存放数据
依然可以通过分析后端的block块,对文件进行恢复,因为block块保存着真实的数据,理论上可以作完整的找回数据
风险: 如果有进程在不断往磁盘写数据时,需要申请新的block块,如果操作系统分配已删除文件的 block 块时,那么新的写入数据就会覆盖 block 原来的数据,这时就会造成数据真正丢失
如果出现这样场景造成数据误删除,需要第一时间 umount 目录所在的磁盘设备,如果没有其他进程在不断地往同一个磁盘块(block)里写数据,那么你的数据理论上还是在 block 块里面,依然可以通过相关分析把数据找回
场景一案例:
[root@localhost tmp]# mkdir /jjb [root@localhost tmp]# cd /jjb [root@localhost jjb]# echo 666 >1.txt [root@localhost jjb]# cat 1.txt 666 [root@localhost jjb]# nohup tail -f 1.txt & # 让tail进程使用该文件(注意此处tail -f可以,但tail -F和tailf不行,原因见后文拓展) [1] 50589 [root@localhost jjb]# nohup: ignoring input and appending output to ‘nohup.out’ [root@localhost jjb]# ls 1.txt nohup.out [root@localhost jjb]# rm -f 1.txt [root@localhost jjb]# ls nohup.out [root@localhost jjb]# ps -ef|grep 1.txt root 49574 48188 0 16:21 pts/1 00:00:00 tail -f 1.txt # 这是之前另一个文件的测试 root 50589 49078 0 16:41 pts/2 00:00:00 tail -f 1.txt root 50619 49078 0 16:42 pts/2 00:00:00 grep --color=auto 1.txt [root@localhost jjb]# lsof |grep 1.txt tail 49574 root 3r REG 8,2 8 125435 /tmp/1.txt # 用lsof命令可以看出更详细的情况 tail 50589 root 3r REG 8,2 4 168226460 /jjb/1.txt (deleted) [root@localhost jjb]# ll /proc/50589/fd/ #通过PID找到该进程使用的文件句柄 total 0 l-wx------ 1 root root 64 Jun 14 16:42 0 -> /dev/null l-wx------ 1 root root 64 Jun 14 16:42 1 -> /jjb/nohup.out l-wx------ 1 root root 64 Jun 14 16:42 2 -> /jjb/nohup.out lr-x------ 1 root root 64 Jun 14 16:42 3 -> /jjb/1.txt (deleted) lr-x------ 1 root root 64 Jun 14 16:42 4 -> anon_inode:inotify lrwx------ 1 root root 64 Jun 14 16:42 6 -> /dev/pts/2 [root@localhost jjb]# cp /proc/50589/fd/3 ./ [root@localhost jjb]# ll total 8 -rw-r--r-- 1 root root 4 Jun 14 16:43 3 -rw------- 1 root root 4 Jun 14 16:41 nohup.out [root@localhost jjb]# cat 3 # 此文件即恢复删除的文件,改回文件名即可 666 [root@localhost jjb]#
拓展1:
https://blog.csdn.net/aguoxin/article/details/103975081 tailf、tail -f、tail -F三者区别实时跟踪文件语法:实时查看日志信息,是排错跟踪问题的重要手段,目前我们常用的命令有, tail -f和tailf。tail -f等同于–follow=descriptor,根据文件描述符进行追踪,当文件改名或被删除,追踪停止。tail -F等同于-follow=name-retry,根据文件名进行追踪,并保持重试,即该文件被删除或改名后,如果再次创建相同的文件名,会继续追踪。tailf等同于tail -f -n 10 (tail -f或-F默认也是打印最后10行) ,与tail -f不同的是,如果文件不增长,它不会去访问磁盘文件,所以tailf特别适合那些便携机上跟踪日志文件,因为它减少了磁盘访问,可以省电。实时跟踪语法区别:不同点:对于小文件(大约小于5GB)使用tailf, tail -f 没有明显区别。 一次偶然使用tailf查看一个20GB日志文件时, 发现无法显示,而使用tail -f却可以显示。当获取文件信息方式不同(stat通过文件名,fstat通过文件描述符),导致当查看文件被删除时,tailf可以获取到文件被删除,tail f获取不到。由于tail-f使用文件描述符,所以即使查看过程中文件名更改tail -f依旧可以获取到文件内容,而tailf 则无法继续查看文件。共同点:打印文件后10行,文件增长读取文件。通过linuxstat命令查看文件信息, tailf和tai1 -f首次访问会改变文件访问时间,如果文件未改变则不会刷新文件访问时间,文件内容改变会再次访问文件并刷新文件访问时间。
场景二案例:
# 服务器上添加一块磁盘 [root@localhost ~]# lsblk #此时还看不到添加的磁盘。方式一:重启 方式二:echo "- - -" >/sys/class/scsi_host/host$i/scan见后文拓展 NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 2G 0 part [SWAP] └─sda2 8:2 0 98G 0 part / sr0 11:0 1 1024M 0 rom [root@localhost ~]# for ((i=0;i<`ls /sys/class/scsi_host/|wc -l`;i++));do echo "- - -" >/sys/class/scsi_host/host$i/scan;done [root@localhost ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 2G 0 part [SWAP] └─sda2 8:2 0 98G 0 part / sdb 8:16 0 1G 0 disk # 加载到新加磁盘了 sr0 11:0 1 1024M 0 rom [root@localhost ~]# fdisk -l Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk label type: dos Disk identifier: 0x000d9529 Device Boot Start End Blocks Id System /dev/sda1 2048 4196351 2097152 82 Linux swap / Solaris /dev/sda2 4196352 209715199 102759424 83 Linux Disk /dev/sdb: 1073 MB, 1073741824 bytes, 2097152 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes [root@localhost ~]# [root@localhost ~]# fdisk /dev/sdb # 分区 Welcome to fdisk (util-linux 2.23.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Device does not contain a recognized partition table Building a new DOS disklabel with disk identifier 0xfeef18c2. Command (m for help): n Partition type: p primary (0 primary, 0 extended, 4 free) e extended Select (default p): Using default response p Partition number (1-4, default 1): First sector (2048-2097151, default 2048): Using default value 2048 Last sector, +sectors or +size{K,M,G} (2048-2097151, default 2097151): Using default value 2097151 Partition 1 of type Linux and of size 1023 MiB is set Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks. [root@localhost ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 2G 0 part [SWAP] └─sda2 8:2 0 98G 0 part / sdb 8:16 0 1G 0 disk └─sdb1 8:17 0 1023M 0 part sr0 11:0 1 1024M 0 rom [root@localhost ~]# mkfs. mkfs.btrfs mkfs.cramfs mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.minix mkfs.xfs [root@localhost ~]# mkfs.ext4 /dev/sdb # 格式化 sdb sdb1 [root@localhost ~]# mkfs.ext4 /dev/sdb1 mke2fs 1.42.9 (28-Dec-2013) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 65536 inodes, 261888 blocks 13094 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=268435456 8 block groups 32768 blocks per group, 32768 fragments per group 8192 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done [root@localhost ~]# [root@localhost ~]# mkdir -p /mnt/test [root@localhost ~]# mount /dev/sdb1 /mnt/test # 挂载 [root@localhost ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 98G 27G 72G 27% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 1.9G 76M 1.8G 5% /run tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup tmpfs 378M 0 378M 0% /run/user/0 /dev/sdb1 991M 2.6M 922M 1% /mnt/test [root@localhost ~]# [root@localhost test]# cd /mnt/test/ [root@localhost test]# ls lost+found [root@localhost test]# echo 888 >2.txt [root@localhost test]# ls 2.txt lost+found [root@localhost test]# cat 2.txt 888 [root@localhost test]# mkdir testdir [root@localhost test]# ls 2.txt lost+found testdir [root@localhost test]# rm -rf ./* [root@localhost test]# ls [root@localhost test]# cd [root@localhost ~]# umount /mnt/test/ # 第一时间卸载磁盘,防止数据继续写入 [root@localhost ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 98G 27G 72G 27% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 1.9G 76M 1.8G 5% /run tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup tmpfs 378M 0 378M 0% /run/user/0 [root@localhost ~]# [root@localhost ~]# yum install extundelete # 安装数据恢复工具 [root@localhost ~]# extundelete /dev/sdb1 --inode 2 # 查看待回复磁盘的根目录iNode信息 (磁盘卸载后无需挂载,安装在服务器上就行) NOTICE: Extended attributes are not restored. WARNING: EXT3_FEATURE_INCOMPAT_RECOVER is set. The partition should be unmounted to undelete any files without further data loss. If the partition is not currently mounted, this message indicates it was improperly unmounted, and you should run fsck before continuing. If you decide to continue, extundelete may overwrite some of the deleted files and make recovering those files impossible. You should unmount the file system and check it with fsck before using extundelete. Would you like to continue? (y/n) y Loading filesystem metadata ... 8 groups loaded. Group: 0 Contents of inode 2: 0000 | ed 41 00 00 00 10 00 00 1b 63 8a 64 0a 63 8a 64 | .A.......c.d.c.d 0010 | 0a 63 8a 64 00 00 00 00 00 00 02 00 08 00 00 00 | .c.d............ 0020 | 00 00 08 00 05 00 00 00 0a f3 01 00 04 00 00 00 | ................ 0030 | 00 00 00 00 00 00 00 00 01 00 00 00 89 00 00 00 | ................ 0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 0080 | 1c 00 00 00 6c bb f6 7d 6c bb f6 7d 58 74 ef 13 | ....l..}l..}Xt.. 0090 | b3 8f 89 64 00 00 00 00 00 00 00 00 00 00 00 00 | ...d............ 00a0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00b0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00c0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00d0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00e0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 00f0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ Inode is Allocated File mode: 16877 Low 16 bits of Owner Uid: 0 Size in bytes: 4096 Access time: 1686790939 Creation time: 1686790922 Modification time: 1686790922 Deletion Time: 0 Low 16 bits of Group Id: 0 Links count: 2 Blocks count: 8 File flags: 524288 File version (for NFS): 0 File ACL: 0 Directory ACL: 0 Fragment address: 0 Direct blocks: 127754, 4, 0, 0, 1, 137, 0, 0, 0, 0, 0, 0 Indirect block: 0 Double indirect block: 0 Triple indirect block: 0 File name | Inode number | Deleted status . 2 .. 2 lost+found 11 Deleted 2.txt 12 Deleted # 可以看到状态为deleted的被删文件 testdir 8193 Deleted [root@localhost jjb]# extundelete /dev/sdb1 --restore-all # 执行恢复,但是...额...我这里恢复失败 NOTICE: Extended attributes are not restored. Loading filesystem metadata ... 8 groups loaded. Loading journal descriptors ... Segmentation fault (core dumped)
拓展2:
http://www.itpub.net/thread-2122014-1-1.html Linux添加磁盘后不重启加载磁盘ls /sys/class/scsi_hostecho “- – -” >/sys/class/scsi_host/host*/scan简单的说:操作系统识别硬件设备是通过硬件驱动来完成的,不同的厂商的硬件,使用的驱动不一样。你说的这个文件其实就是 HBA卡 或者scsi卡的驱动的入口文件,不同的驱动,入口文件的名字(目录)都不一样echo “- – -” >/sys/class/scsi_host/host*/scan 其中 — 就是一个标识,当驱动程序再入口文件中读取到这个标识后,就会触发重新识别磁盘的操作(不同驱动的标识也不一样)你可以看看 emulex 和qlogic的卡,他们触发识别磁盘的方法,是完全不一样的。
拓展3:
https://blog.csdn.net/qq_39652397/article/details/124020874 Linux数据恢复工具之extundeleteextundelete的恢复原理:在Linux下可以通过”ls -id”命令来查看某个文件或者目录的inode值,例如查看根目录的inode值,可以输入:ls -id / 由此可知,根目录的inode值一般为2。在利用extundelete恢复文件时并不依赖特定文件格式,首先extundelete会通过文件系统的inode信息(根目录的inode一般为2)来获得当前文件系统下所有文件的信息,包括存在的和已经删除的文件,这些信息包括文件名和inode。然后利用inode信息结合日志去查询该inode所在的block位置,包括直接块,间接块等信息。最后利用dd命令将这些信息备份出来,从而恢复数据文件。其中,参数(options)有:–version,-[VV],显示软件版本号。–help,显示软件帮助信息。–superblock,显示超级块信息。–journal,显示日志信息。–after dtime,时间参数,表示在某段时间之后被删的文件或目录。–before dtime,时间参数,表示在某段时间之前被删的文件或目录。动作(action)有:–inode ino,显示节点“ino”的信息。–block blk,显示数据块”blk”的信息。–restore-inode ino[,ino,…],恢复命令参数,表示恢复节点”ino”的文件,恢复的文件会自动放在当前目录下的RESTORED_FILES文件夹中,使用节点编号作为扩展名。–restore-file path,恢复命令参数,表示将恢复指定路径的文件,并把恢复的文件放在当前目录下的RECOVERED_FILES目录中。–restore-files path,恢复命令参数,表示将恢复在路径中已列出的所有文件。–restore-all 恢复命令参数,表示将尝试恢复所有目录和文件。-j journal 表示从已经命名的文件中读取扩展日志。-b blocknumber,表示使用之前备份的超级块来打开文件系统,一般用于查看现有超级块是不是当前所要的文件。-B blocksize,通过指定数据块大小来打开文件系统,一般用于查看已经知道大小的文件