我们最近做的项目是和多方合作,系统依赖的很多程序和设置都来自第三方,系统的运行环境全都做在了一块硬盘里。从我们拿到这块硬盘起系统的运行就没有正常过。经过多日的调试,可以判断出是依赖的一些库和配置文件有错误,导致软件运行异常。多次协调对方也不愿意提供更多关于修复安装和配置的信息(当然可能他们也不知道)。项目开始时没有人留意,出了事故才发现,整个项目的开发过程中,能运行系统的环境竟然在唯一的一块硬盘上。简直是这辈子最苦逼的开发体验,所有人都很重视,所有领导都每天询问,各种高级工程师秒回你的邮件。但是…但是所有的细节都是秘密,所有问实现,问原理,求指导的问题都不正面回答,要求一个纯净的可用的硬盘也没人答复,所有人都等着你探索黑盒子里的秘密……
当然我是幸运的,最后通过其他途径找到一台还能运行的旧版设备,使用硬盘对拷的办法,在一块新的硬盘上克隆了全部运行环境,基于这个环境才搭起了系统。
系统备份和恢复工具选择很多,Windows下的各种一键复原,Mac os下的高大上的Time Machine,Linux下也有Clonezilla这样的全能选手。当然不求助第三方软件,最基本的linux dd 命令也能完成这些功能。这一次紧急情况下,正是这个在只有五寸屏的PowerPC Linux上也有的命令,救了大家一命。
dd命令
dd是Unix/Linux下转换和复制文件的命令,名字和用法都稍显怪异,据说来源于IBM的Job Control Language,意为Data Description。
dd命令秉承Unix哲学,专注文件复制和以及复制过程中的格式转换。但是类Unix操作系统下,万物皆文件,dd命令可以像对待普通文件一样,操作硬件的设备驱动和特殊设备文件等资源,这就赋予了dd命令各种不同的用途:驱动器性能测试,数据恢复,磁盘擦除,修复引导记录……
磁盘备份
使用fdisk 先查看磁盘分区,找到硬盘的位置。
1 | sudo fdisk -u -l |
我的情况是需要用一块硬盘完全克隆另一块,只需要指明输入输出的硬盘文件路径就可以了。
1 | sudo dd if=/dev/sda of=/dev/sdb |
也可以将磁盘备份到image文件。需要注意的是,dd命令是按照文件块操作,如果不指明块的大小和数量,dd命令会对全部硬盘进行复制,并不会跳过磁盘未使用的空间。一定要确保目标文件比原来的磁盘文件大。
1 | sudo dd if=/dev/sda of=~/disk1.img |
一般情况下,对image文件压缩是更有效的方法。大部分压缩算法会把空白部分完全压缩,只留下标记,对只使用了很少的磁盘文件,可以得到很好的压缩比。
1 | sudo dd if=/dev/sda | gzip > disk.img.gz |
需要恢复时,一样的解压拷贝
1 | gzip -dc /disk.img.gz | dd of=/dev/sda |
显示dd进度
dd命令执行相当的耗时,我100G的硬盘大概用了2个小时,期间dd进程并不反馈任何信息,对用户来说是相当痛苦的等待。其实查看dd的help信息,可以发现如果dd进程收到SIGSUR1 signal,就会在console打印出dd的当前状态,help中也给出了示例的脚本。
1 | $ dd --help |
如果要定时更新状态,可以配合watch命令
1 | sudo watch -n 5 pkill -USR1 ^dd$ |
每隔5秒钟打印dd的信息。
1 | 208485885+0 records in |