Skip to content
learnMachining edited this page Apr 15, 2017 · 5 revisions

硬盘雪崩之后


0x01 就是雪崩

  一周之前,硬盘无奈的坏掉了,文件变成了几十个大小不一的乱码块,原来NTFS文件系统变成了FAT32,但硬盘容量不降反升。当时第一反应就是硬盘的分区表错乱,文件系统底层崩坏。用DiskGenius自带的数据恢复功能恢复数据未果后,使用chkdsk /f命令进行磁盘文件系统修复。电脑日夜不停地跑了一周,结果如下:

大雪崩图片

  没错,命令在一个接一个cluster地进行修复,并且这一周都是如此!我的移动硬盘容量2T,一个cluster的容量是4K~16K,粗略算一下,完全修复完成大概需要(2048 * 1024 * 1024 / 4) * 7 / 48079870 = 78.16 天,还不保证完成之后数据一定能够恢复,毕竟我原来的文件系统是NTFS,而非FAT32。是的,这不是伤筋动骨,这是粉身碎骨,这就是雪崩。

  所以有必要思考一下如何避免再次发生这样的惨剧。

0x02 数据会遭遇什么

  为了更好地保护自己的数据,首先需要了解数据会因为什么原因而遭受到损坏。对于普通的学生党、上班族来说,数据主要会因为以下几种原因而遭到破坏:

  • 操作不当。包括误删文件,以及一些对硬盘的操作,如错误格式化,错误分区,制作引导盘时错误选择磁盘等;绝大多数数据破坏都是由于操作不当引起,包括我这次的数据毁坏

  • 存储介质损坏。最常见的如机械硬盘磁头损坏,硬盘内所有数据都无法正常访问,SSD,U盘都有一定的寿命,读写次数超过寿命时无法正常获取其中的文件

  • 恶意代码破坏。如病毒感染文件,影响文件的正常访问,或者勒索软件加密磁盘上的文件;这种情况较少,但身边也有人遇到,需要防范

0x03 关于备份

  备份和冗余在数据保护方面的作用是不可替代的,这也是最好的保护数据的方式,但对于如何进行备份却有些讲究。

  对于生产环境,完全可以使用RAID、多地灾备以及一些高级的数据备份策略,但对于普通人,一来没有那么多金钱和精力,二来也没有那么多重要的数据。只需要简单的备份策略就已经足够,如单向同步,增量同步,完全备份,增量备份等。

  一种有效的备份策略是,如果要备份系统等规模较大的数据,可以考虑先进行完全备份,之后进行增量备份或差异备份;如果要备份的数据是日常工作区内的文件,则可以使用增量同步或者单向同步,以增量同步为首选。

  另外还有其他需要注意的问题。其一,备份的文件和原始文件最好存放在不同的硬盘之中。由于磁盘物理损坏会影响磁盘内的所有文件,磁盘误操作也往往影响整块磁盘,此时在同一块磁盘上的不同分区备份就会失效;其二,可以考虑在不同的文件系统下进行备份,例如使用ext3ext4文件系统备份windows上的文件,由于windows不支持日志文件系统,这样可以有效防止windows下的病毒和勒索软件对备份数据进行破坏,避免数据全军覆没。

  最后,推荐一款windows下进行备份的软件,FileGee文件同步备份系统。该软件支持各种备份和同步策略,完全备份,增量备份,单向同步,双向同步,以及增量同步都有支持,并且还有个人的免费版本。
传送门

0x04 数据分层

  记得大二一个又高又胖的老师曾经说过,能够快速地从旧的文件中找到需要的内容,是一种很强的能力,我对此深表赞同。但那说的是关于数据归档分类方面的事情,而这里所说的数据分层是以数据备份为基准,把数据分出层次。

  每一个人都有自己的备份策略和和相应的数据分层标准,我想把数据分成以下三层是一种可行的策略:

  • commit core:最核心的数据,如工作的文档,私人的照片,程序源码等。这部分数据应当在本地进行增量同步,防止误删除,由于体积较小,也可以进行云备份。
  • commit common:包含commit core,是准备长时间保存的数据,如音乐专辑,电影,电子书籍,系统安装镜像,常用的软件工作区等。这部分数据也应当进行本地备份,但因为数据量大,不适合云备份。
  • stage:不需要备份的数据。如下载的软件安装包,准备尝鲜看的电影等。这部分数据最大,虽然不需要备份,但是有必要知道这部分数据都有什么,记录数据的元信息。

  实际工作时,如果知道新文件属于哪一层,可以直接放入相应的层中;如果不确定,则放入下一层,待需要更强的备份策略时再放入更高层。例如,从网上下载的电影可先放入stage,看完之后如果认为具有收藏价值,则放入commit common,否则就让它继续待在stage,清理磁盘时删掉它。

0x05 克隆文件系统树

  对于文件系统中的数据,尤其是stage中的数据,应当记录其中存储了哪些文件。可以通过克隆一个文件系统树来完成。也就是按照原来的目录结构创建完全一样的目录树,但并不拷贝目录中的文件,而只记录文件的名字和大小等信息。

  下面是一个windows下完成此项功能的批处理文件,在我的windows10系统中工作良好。

@echo off
@rem chage page code to utf-8
chcp 65001

echo begin clone
date /t
time /t
set "drivers=a b c d e f g h i j k l m n o p q r s t u v w x y z"
@rem user dependent batch file parameters, set firstly
set "cloneRootDirectory=d:\cloneFileSystemTree"
set "cloneRootDirectory2=c:\cloneFileSystemTree"
set "maxDepth=4"

@rem to run more than once, delete old file system tree
if exist "%cloneRootDirectory%" (
	rd /S /Q "%cloneRootDirectory%"
)
md "%cloneRootDirectory%"
if exist "%cloneRootDirectory2%" (
	rd /S /Q "%cloneRootDirectory2%"
)
md "%cloneRootDirectory2%"
for %%i in (%drivers%) do (
	if exist %%i: (
		call :clone "root","%%i:",%maxDepth%
	)
)

date /t
time /t
echo clone end
@rem clear variables
set drivers=
set cloneRootDirectory=
set cloneRootDirectory2=
set maxDepth=
goto:eof


@rem @param %1 parent directory
@rem @param %2 current directory name
@rem @param %3 left depth
:clone 
setlocal
	@rem process parameters
	set "firstParam=%~1"
	set "secondParam=%~2"
	set "leftDepth=%3"
	set /A "leftDepth-=1"

	if "%firstParam%"=="root" (
		set "currentDirectory=%secondParam%"
	) else (
		set "currentDirectory=%firstParam%\%secondParam%"
	)
	echo "%currentDirectory%"
	set "cloneCurrentDirectory=%cloneRootDirectory%\%currentDirectory::=%"
	set "cloneCurrentDirectory2=%cloneRootDirectory2%\%currentDirectory::=%"

	@rem filter
	if "%cloneRootDirectory%"=="%currentDirectory%" (
		goto:eof
	)
	if "%cloneRootDirectory2%"=="%currentDirectory%" (
		goto:eof
	)

	@rem  create clone directory
	if not exist "\\?\%cloneCurrentDirectory%" (
		md "\\?\%cloneCurrentDirectory%\"
	)
	if not exist "\\?\%cloneCurrentDirectory2%" (
		md "\\?\%cloneCurrentDirectory2%\"
	)

	@rem check left depth
	if %leftDepth% equ 0 (
		tree /F "%currentDirectory%" > "%cloneCurrentDirectory%\%secondParam::=%_tree.txt"
		tree /F "%currentDirectory%" > "%cloneCurrentDirectory2%\%secondParam::=%_tree.txt"
		goto :eof
	)

	set "cloneFFile=%cloneCurrentDirectory%\%secondParam::=%_files.txt"
	set "cloneFFile2=%cloneCurrentDirectory2%\%secondParam::=%_files.txt"
	set "cloneDFile=%cloneCurrentDirectory%\%secondParam::=%_directories.txt"
	set "cloneDFile2=%cloneCurrentDirectory2%\%secondParam::=%_directories.txt"

	@rem record file names
	dir /A-D-S "\\?\%currentDirectory%\" > nul 2>&1
	if %errorlevel% equ 0 (
		dir /A-D-S "\\?\%currentDirectory%\" > "\\?\%cloneFFile%"
		dir /A-D-S "\\?\%currentDirectory%\" > "\\?\%cloneFFile2%"
	)

	@rem recursively clone, nestedly record directory names
	for /f "delims=" %%i in ('dir /AD-S /B "\\?\%currentDirectory%\"') do (
		if not exist "\\?\%cloneDFile%" (
			dir /AD-S "\\?\%currentDirectory%\" > "\\?\%cloneDFile%"
		)
		if not exist "\\?\%cloneDFile2%" (
			dir /AD-S "\\?\%currentDirectory%\" > "\\?\%cloneDFile2%"
		)

		@rem process directory name that contains percent sign
		echo "%%i" | findstr /C:"%%" > nul
		if errorlevel 1 (
			call :clone "%currentDirectory%","%%i",%leftDepth%
		) else (
			tree /F "%currentDirectory%\%%i" > "%cloneCurrentDirectory%\%secondParam::=%_%%i_tree.txt"
			tree /F "%currentDirectory%\%%i" > "%cloneCurrentDirectory2%\%secondParam::=%_%%i_tree.txt"
		)
	) 
endlocal
goto:eof

  最后,数据无价,谨慎操作