热备份虚拟机一般说来有2种方法:
第1种方法在虚拟机Guest OS里安装备份软件或备份代理,如Symantec的Livestate和Ghost、Veritas的NetBackup和Backup Exec、IBM的TSM、Legate的Networker、CA的ArcServer、Acronis的TrueImageServer……由于备份方法与真实计算机完全一致,各备份软件又相对非常成熟,所以本篇不做介绍,有感兴趣的朋友请参考各软件的用户手册。
第2种方法是用拷贝虚拟机磁盘*.vmdk文件来达到备份目的的。看过第2篇日志的会有疑问,继续用vmkfstools -e输出*.vmdk不就行了吗?很抱歉,在运行虚拟机的时候该文件是不能被我们访问的!
正确的方法是先创建Redo日志,日志创建后,*.vmdk文件将不再发生变化,所有新生成的数据只往Redo日志中写入!这时我们就可以用vmkfstools -e输出*.vmdk文件了。
软件准备:
从
http://www.vmware.com/pdf/ESXBackup.pdf 下载pdf手册,在第8页开始有3段perl代码,我们需要把addredo.pl和commitnext.pl代码用选择工具复制到记事本中,再另存为addredo.pl和commitnext.pl文件,然后再把commitnext.pl复制一份,取名为committop.pl,编辑committop.pl文件,找到$err = $vm-<commit($disk, 1, 0, 1);这一行,把它改成$err = $vm-<commit($disk, 0, 0, 1);保存推出。通过FTP把这3个文件上传到ESX中。
备份步骤:以 root身份登录,虚拟机必须是开启状态
1.创建redo日志
命令:perl addredo.pl
其中是虚拟机的配置文件,一般在/root/vmware/下的文件夹下
命令执行成功后将在*.vmdk目录下生成一个*.vmdk.REDO文件,刚创建出来的尺寸是16M,随着数据的写入将会不断增大
2.输出*.vmdk文件
命令:vmkfstools -e
参数见
(二)
3.创建第2个redo日志
命令:perl addredo.pl
*.vmdk目录下会生成*.vmdk.REDO.REDO文件
作用:如果*.vmdk文件很大,步骤2输出文件的时间将会很长,在这之前产生的数据就备份不到了。所以需要再生成第2个日志,这样就可以把第1个日志也备份了。
4.把生成第1个redo日志与输出的*.vmdk文件拷贝到一起
5.用VBUE备份文件
6.提交日志
命令:perl commitnext.pl
把日志写回到*.vmdk中
7.提交另1个日志:
命令:perl committop.pl
把另1个日志写回到*.vmdk中
之后我做了2个有趣的小实验:
Windows 2003的虚拟机,用Flashget下载内网FTP服务器上的1个1G大小的文件,限速70K/S
1.生成第1个redo,用Flashget开始下载,输出*.vmdk文件,这时候已经下载到2M多了,等下载到4M多时,生成第2个redo,把第1个redo拷贝走
实验:用输出的vmdk和第1个redo日志做恢复,下载量只能恢复到1M多的程度
2.生成第1个redo,用Flashget开始下载,输出*.vmdk文件,突然我强行关闭电源,555555555硬盘啊。接通电源开启虚拟机,Vmware提示发现redo日志,问是否提交日志?


可是无论是否提交日志,都只能恢复到未下载前的水平。
附:addredo.pl、commitnext.pl内容,committop按前面的方法修改。
#addredo.pl
#!/usr/bin/perl
use VMware::Control::Server;
use VMware::Control::VM;
$cfg = $ARGV[0];
$disk = $ARGV[1];
$cfgDir = substr($cfg, 0, rindex($cfg, "/"));
$cfgName = substr($cfg, rindex($cfg, "/")+1);
$server = VMware::Control::Server::new();
#!/usr/bin/perl
use VMware::Control::Server;
use VMware::Control::VM;
$cfg = $ARGV[0];
$disk = $ARGV[1];
$cfgDir = substr($cfg, 0, rindex($cfg, "/"));
$cfgName = substr($cfg, rindex($cfg, "/")+1);
$server = VMware::Control::Server::new();
$err = $server-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $server-<get_last_error();
#print “Server connect error: “, $errorString, "\n";
exit;
}
$vm = VMware::Control::VM::new($server, $cfg);
$err = $vm-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $vm-<get_last_error();
#print "VM connect error: ", $errorString, "\n";
exit;
}
if (!defined($err)) {
($errorNumber, $errorString) = $server-<get_last_error();
#print “Server connect error: “, $errorString, "\n";
exit;
}
$vm = VMware::Control::VM::new($server, $cfg);
$err = $vm-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $vm-<get_last_error();
#print "VM connect error: ", $errorString, "\n";
exit;
}
@devices = @{ $vm-<get("Status.devices") };
$ndisk = 1;
foreach $disk (@devices) {
if ($disk =~ "ethernet" || $disk !~ ":") {
next;
}
if ($vm-<get("Config.$disk.deviceType") eq "atapi-cdrom") {
next;
}
print "$ndisk: $disk\n";
$ndisk++;
push(@disks, $disk);
}
if ($disk eq '') {
print "Which disk (specify number): ";
$ndisk = 1;
foreach $disk (@devices) {
if ($disk =~ "ethernet" || $disk !~ ":") {
next;
}
if ($vm-<get("Config.$disk.deviceType") eq "atapi-cdrom") {
next;
}
print "$ndisk: $disk\n";
$ndisk++;
push(@disks, $disk);
}
if ($disk eq '') {
print "Which disk (specify number): ";
$opt = ;
if ($opt < opt >= $ndisk) {
print "Illegal disk number\n";
exit;
}
$disk = $disks[$opt-1];
}
$err = $vm-<add_redo($disk);
if (!defined($err)) {
($errorNumber, $errorString) = $vm-<get_last_error();
#print "VM commit error: ", $errorString, "\n";
exit;
}
$vm-<disconnect();
$server-<disconnect();
if ($opt < opt >= $ndisk) {
print "Illegal disk number\n";
exit;
}
$disk = $disks[$opt-1];
}
$err = $vm-<add_redo($disk);
if (!defined($err)) {
($errorNumber, $errorString) = $vm-<get_last_error();
#print "VM commit error: ", $errorString, "\n";
exit;
}
$vm-<disconnect();
$server-<disconnect();
###############################################
#commitnext.pl
#!/usr/bin/perl
use VMware::Control::Server;
use VMware::Control::VM;
$cfg = $ARGV[0];
$machine = $ARGV[1];
$disk = $ARGV[2];
$cfgDir = substr($cfg, 0, rindex($cfg, "/"));
$cfgName = substr($cfg, rindex($cfg, "/")+1);
$server = VMware::Control::Server::new();
$err = $server-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $server-<get_last_error();
print "Server connect error: ", $errorString, "\n";
exit;
}
$vm = VMware::Control::VM::new($server, $cfg);
$err = $vm-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $vm-<get_last_error();
print "VM connect error: ", $errorString, "\n";
exit;
}
@devices = @{ $vm-<get("Status.devices") };
$ndisk = 1;
foreach $disk (@devices) { if ($disk =~ "ethernet" || $disk !~ ":") {
next;
}
if ($vm-<get("Config.$disk.deviceType") eq "atapi-cdrom") {
next;
}
print "$ndisk: $disk\n";
$ndisk++;
push(@disks, $disk);
}
if ($disk eq '') {
print "Which disk (specify number): ";
$opt = ;
if ($opt < opt >= $ndisk) {
print "Illegal disk number\n";
exit;
}
$disk = $disks[$opt-1];
}
print "Committing disk $disk\n";
$err = $vm-<commit($disk, 1, 0, 1);
if (!defined($err)) { ($errorNumber, $errorString) = $vm-<get_last_error();
print "VM commit error: ", $errorString, "\n";
exit;
}
$vm-<disconnect();
$server-<disconnect();
use VMware::Control::Server;
use VMware::Control::VM;
$cfg = $ARGV[0];
$machine = $ARGV[1];
$disk = $ARGV[2];
$cfgDir = substr($cfg, 0, rindex($cfg, "/"));
$cfgName = substr($cfg, rindex($cfg, "/")+1);
$server = VMware::Control::Server::new();
$err = $server-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $server-<get_last_error();
print "Server connect error: ", $errorString, "\n";
exit;
}
$vm = VMware::Control::VM::new($server, $cfg);
$err = $vm-<connect();
if (!defined($err)) {
($errorNumber, $errorString) = $vm-<get_last_error();
print "VM connect error: ", $errorString, "\n";
exit;
}
@devices = @{ $vm-<get("Status.devices") };
$ndisk = 1;
foreach $disk (@devices) { if ($disk =~ "ethernet" || $disk !~ ":") {
next;
}
if ($vm-<get("Config.$disk.deviceType") eq "atapi-cdrom") {
next;
}
print "$ndisk: $disk\n";
$ndisk++;
push(@disks, $disk);
}
if ($disk eq '') {
print "Which disk (specify number): ";
$opt = ;
if ($opt < opt >= $ndisk) {
print "Illegal disk number\n";
exit;
}
$disk = $disks[$opt-1];
}
print "Committing disk $disk\n";
$err = $vm-<commit($disk, 1, 0, 1);
if (!defined($err)) { ($errorNumber, $errorString) = $vm-<get_last_error();
print "VM commit error: ", $errorString, "\n";
exit;
}
$vm-<disconnect();
$server-<disconnect();



