Linux备份还原双系统设计与实现(一)

1、设计目的
    linux因其知名的稳定性,广泛应用于工业产品,但仍可能因为突然断电等不可预知的原因导致系统崩溃或不稳定现象出现。对于已经安装运行的项目,比如现在常见的广告机系统,运维工程师前往现场处理的时间、经济成本会比较高。如果设计成双系统,一个系统专用于日常运行,一个系统专用于备份、还原工作,同时提供方便的还原操作方式,那么一旦出现系统崩溃,最终用户可以自行操作,把系统还原到初始状态,这样就把系统崩溃造成的影响和损失降到最低。
 
2、设计思路
    硬盘分为4个区,第一个分区安装专用于备份还原的操作系统A(以下简称系统A),第二个分区安装工作用的操作系统B(以下简称系统B),第三个分区用于数据区,第四个分区用于交换分区。单独分出数据区的好处在于还原操作系统后,不影响应用程序和业务数据,同时还可以把应用程序或业务数据进行单独备份还原。类似于windows的C盘安装操作系统,工作文档放在D盘,一旦格式化C盘重装系统,D盘的文档还在。
    分区图如下:
 
    在linux引导程序grub菜单中设置不同的引导菜单,主要包括:【备份】、【还原】,【正常】。默认引导【正常】菜单进入正常工作模式,一旦用户在开机时按下特殊键(如Shilft),就显示其它的操作菜单供用户选择。如果用户选择【备份】或【还原】操作,则进入备份还原的系统A中,系统A首先取得Grub的引导参数,然后根据参数利用tar工具进行具体备份或还原的操作。
 
3、具体实现
    以下以ubuntu 12.04为例进行说明。
 
3.1 安装操作系统
    推荐下载ubuntu 12.04 alternate版本,然后最小化安装,再根据需要安装其它的组件。
    刻录成光盘或者使用U盘安装,如果使用U盘安装,推荐U盘安装工具unetbootin。下载地址: http://dw10.cn.uptodown.com/dm/1381334630/2f71d6e1d597180c9cfbdd6856698d2799c76279/unetbootin-5-84-es-en-win-setup.exe
    
    先安装操作系统B,再安装系统A,安装详细操作可参考互联网公开资料。主要步骤如下:
    1、安装操作系统B时,在第一个菜单出现时,按F4,然后选择最小化安装。
    2、选择硬盘分区时,手动分成4个区,其中分区1不挂载,系统B安装在分区2,同时把分区3挂载到系统B的数据区,SWAP交换分区设置在分区4。
    3、根据引导安装系统B完毕。
    4、重启进入系统B,根据实际情况安装必要的组件,比如基本桌面,vim, ssh等。
    5、修改系统的分区表。因为ubuntu 12.04使用UUID标识硬盘分区,在还原操作时,会格式化分区1并产生新的UUID,从而导致操作系统因为找不到分区进不了系统。修改如下:
#删除UUID,直接使用/dev/sda2标识分区2
/dev/sda2 /               ext4    errors=remount-ro 0       1
/dev/sda3 /home/xds/bin   ext4    defaults        0       2
/dev/sda4 none            swap    sw              0       0
    6、安装系统A的过程和系统B基本一致,区别在于选择分区时,安装到分区1,不挂载数据区,SWAP分区同样设置在分区4。
    
3.2 编辑系统A的grub菜单
注:以下未明确说明在哪个操作系统下的操作,都是在操作系统A(备份还原操作系统)下。
    关键配置说明详见下面的注释。注意把里面标识硬盘的UUID修改为传统的硬盘分区硬盘/dev/sda2之类。
    为防止用户误操作,没有开放【备份操作系统】的菜单。只开放了以下四个菜单 :【还原操作系统】,【备份应用程序】,【还原应用程序】,【拯救模式】,【正常工作系统】。重点信息使用中文做了注释。
    grub配置文件默认只读,需要先设置为可写,修改后,再设置为只读。
sudo chmod +w /boot /grub /grub.cfg
sudo vi /boot /grub /grub.cfg
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#
 
### BEGIN /etc/grub.d/00_header ###
if [ -s $prefix /grubenv ]; then
  set have_grubenv =true
  load_env
fi
#默认进入第4个菜单,也就是正常的系统
set default = "4"
if [ "${prev_saved_entry}" ]; then
  set saved_entry = "${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry =
  save_env prev_saved_entry
  set boot_once =true
fi
 
function savedefault {
   if [ -z "${boot_once}" ]; then
    saved_entry = "${chosen}"
    save_env saved_entry
   fi
}
 
function recordfail {
  set recordfail = 1
   if [ -n "${have_grubenv}" ]; then if [ -z "${boot_once}" ]; then save_env recordfail; fi; fi
}
 
function load_video {
  insmod vbe
  insmod vga
  insmod video_bochs
  insmod video_cirrus
}
 
insmod part_msdos
insmod ext2
set root = '(hd0,msdos1)'
 
if loadfont /usr /share /grub /unicode.pf2 ; then
  set gfxmode =auto
  load_video
  insmod gfxterm
  insmod part_msdos
  insmod ext2
  set root = '(hd0,msdos1)'
 
  set locale_dir =($root) /boot /grub /locale
  set lang =en_US
  insmod gettext
fi
terminal_output gfxterm
if [ "${recordfail}" = 1 ]; then
  set timeout = - 1
else
  set timeout = 10
fi
#设置菜单超时为0,也就是不显示GRUB菜单直接进引导入操作系统
set timeout = 0
### END /etc/grub.d/00_header ###
 
### BEGIN /etc/grub.d/05_debian_theme ###
set menu_color_normal =white /black
set menu_color_highlight =black /light -gray
### END /etc/grub.d/05_debian_theme ###
 
### BEGIN /etc/grub.d/10_linux ###
function gfxmode {
    set gfxpayload = "$1"
     if [ "$1" = "keep" ]; then
        set vt_handoff =vt.handoff = 7
     else
        set vt_handoff =
     fi
}
if [ ${recordfail} != 1 ]; then
   if [ -e ${prefix} /gfxblacklist.txt ]; then
     if hwmatch ${prefix} /gfxblacklist.txt 3; then
       if [ ${match} = 0 ]; then
        set linux_gfx_mode =keep
       else
        set linux_gfx_mode =text
       fi
     else
      set linux_gfx_mode =text
     fi
   else
    set linux_gfx_mode =keep
   fi
else
  set linux_gfx_mode =text
fi
export linux_gfx_mode
if [ "$linux_gfx_mode" != "text" ]; then load_video; fi
#菜单0:还原操作系统
menuentry 'Restore System' --class ubuntu --class gnu -linux --class gnu --class os {
    recordfail
    gfxmode $linux_gfx_mode
    insmod gzio
    insmod part_msdos
    insmod ext2
    set root = '(hd0,msdos1)'
 
    linux     /boot /vmlinuz - 3. 2. 0 - 23 -generic -pae root = /dev /sda1 ro   quiet splash restoreSys $vt_handoff
    initrd     /boot /initrd.img - 3. 2. 0 - 23 -generic -pae
}
#菜单1:还原操作系统
menuentry 'Backup Application' --class ubuntu --class gnu -linux --class gnu --class os {
    recordfail
    gfxmode $linux_gfx_mode
    insmod gzio
    insmod part_msdos
    insmod ext2
    set root = '(hd0,msdos1)'
 
    linux     /boot /vmlinuz - 3. 2. 0 - 23 -generic -pae root = /dev /sda1 ro   quiet splash backupApp $vt_handoff
    initrd     /boot /initrd.img - 3. 2. 0 - 23 -generic -pae
}
#菜单2:还原应用程序
menuentry 'Restore Application' --class ubuntu --class gnu -linux --class gnu --class os {
    recordfail
    gfxmode $linux_gfx_mode
    insmod gzio
    insmod part_msdos
    insmod ext2
    set root = '(hd0,msdos1)'
 
    linux     /boot /vmlinuz - 3. 2. 0 - 23 -generic -pae root = /dev /sda1 ro   quiet splash restoreApp $vt_handoff
    initrd     /boot /initrd.img - 3. 2. 0 - 23 -generic -pae
}
#菜单3:拯救模式
menuentry 'Rescue' --class ubuntu --class gnu -linux --class gnu --class os {
    recordfail
    gfxmode $linux_gfx_mode
    insmod gzio
    insmod part_msdos
    insmod ext2
    set root = '(hd0,msdos1)'
 
    linux     /boot /vmlinuz - 3. 2. 0 - 23 -generic -pae root = /dev /sda1 ro   quiet splash $vt_handoff
    initrd     /boot /initrd.img - 3. 2. 0 - 23 -generic -pae
}
### END /etc/grub.d/10_linux ###
 
### BEGIN /etc/grub.d/20_linux_xen ###
### END /etc/grub.d/20_linux_xen ###
 
### BEGIN /etc/grub.d/20_memtest86+ ###
 
### END /etc/grub.d/20_memtest86+ ###
 
### BEGIN /etc/grub.d/30_os-prober ###
if [ "x${timeout}" != "x-1" ]; then       
   if keystatus; then     
#如果用户在开机时按住shift键,则弹出菜单供用户选择  
     if keystatus --shift; then       
      set timeout = - 1       
     else       
      set timeout = 0       
     fi       
   else       
     if sleep --interruptible 3 ; then       
      set timeout = 0       
     fi       
   fi       
fi    
#菜单4:正常工作系统   
menuentry "XDS" --class gnu -linux --class gnu --class os {
    insmod part_msdos
    insmod ext2
    set root = '(hd0,msdos2)'
 
    linux /boot /vmlinuz - 3. 2. 0 - 23 -generic -pae root = /dev /sda2 ro quiet splash $vt_handoff
    initrd /boot /initrd.img - 3. 2. 0 - 23 -generic -pae
}
 
### END /etc/grub.d/30_os-prober ###
 
### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###
 
### BEGIN /etc/grub.d/41_custom ###
if [ -f  $prefix /custom.cfg ]; then
  source $prefix /custom.cfg;
fi
### END /etc/grub.d/41_custom ###
修改完成后,去除可写属性
sudo chmod -w /boot /grub /grub.cfg
 
3.3 编辑系统A的备份还原脚本
    脚本注释只标注了备份操作系统,其它操作类似。
sudo vi /etc /init.d /xds.rc
#!/bin/bash
PATH =$PATH : /sbin : /usr /sbin : /bin : /usr /bin
 
#备份操作系统
function backupSys
{
touch /tmp /tmpfile
#删除原来的备份
sudo rm /backup /os.tgz   1 > /dev /null 2 > & 1
#挂载分区2,也就是正常工作所在的操作系统B所在的分区
sudo mount -o rw /dev /sda2 /mnt 1 > /dev /null 2 > & 1
#取得需要备份的文件总数,用于显示备份、还原的进度条
total = `sudo find /mnt /   - not -wholename '/mnt/tmp*' |wc -l `
echo $total > /tmp /osTotal
sudo mv /tmp /osTotal /backup /
#使用tar做备份操作,加上&用于在后台执行
sudo tar -cpzvf /backup /os.tgz -C /mnt . --exclude =. /tmp --exclude =. /etc /udev /rules.d / 70 -persistent -net.rules > /tmp /tmpfile &
#以下脚本使用dialog 显示进度,并提示用户不要关闭电源等,以免长时间黑屏导致用户误操作
cur = 0
PCT = 0
end = ` ps -ef   |grep "tar -cpzvf" |wc -l `
(
#while test $total != $cur
while test $end != 1
do
cat <<EOF
XXX
$PCT
It will take a few minutes. Do not press : Ctrl + C.\n\n
Backuping file :\n `tail -n 1 /tmp /tmpfile `
XXX
EOF
cur = `sudo cat /tmp /tmpfile |wc -l `
PCT = ` echo "$cur*100/$total" |bc `
end = ` ps -ef   |grep "tar -cpzvf" |wc -l `
sleep 0. 1
done
) |
dialog --title "Backup System" "$@" --gauge "It will take a few minutes.\nDo not press: Ctrl + C " 12 80 0     
#备份完成 
sudo umount /mnt 1 > /dev /null 2 > & 1      
#(dialog --title "Backup System" --gauge "Backup finished.\nWill reboot... " 12 80 100) | 0
sleep 1
cur = `sudo cat /tmp /tmpfile |wc -l `
echo $cur > /tmp /osTotal
#重启,重启后自动进入正常工作操作系统B
sudo reboot 1 > /dev /null 2 > & 1   
}
 
#备份应用程序
function backupApp
{
touch /tmp /tmpfile
sudo rm /backup /bin.tgz 1 > /dev /null 2 > & 1
sudo mount -o rw /dev /sda3 /mnt 1 > /dev /null 2 > & 1
total = `sudo find /mnt / - not -wholename '/mnt/data*' - not -wholename '/mnt/tmp*' - not -wholename '/mnt/lost+found' |wc -l `
total = `expr $total `
sudo tar -cpzvf /backup /bin.tgz -C /mnt . --exclude =. /data --exclude =. /tmp   --exclude =. /lost +found > /tmp /tmpfile &
cur = 0
PCT = 0
end = ` ps -ef   |grep "tar -cpzvf" |wc -l `
(
#while test $total != $cur
while test $end != 1
do
cat <<EOF
XXX
$PCT
It will take a few minutes. Do not press : Ctrl + C.\n\n
Backuping file :\n `tail -n 1 /tmp /tmpfile `
XXX
EOF
cur = `sudo cat /tmp /tmpfile |wc -l `
PCT = ` echo "$cur*100/$total" |bc `
end = ` ps -ef   |grep "tar -cpzvf" |wc -l `
sleep 0. 1
done
) |
dialog --title "Backup Application" "$@" --gauge "It will take a few minutes.\nDo not press: Ctrl + C " 12 80 0     
sudo umount /mnt 1 > /dev /null 2 > & 1      
#(dialog --title "Backup Application" --gauge "Backup finished.\nWill reboot... " 12 80 100) | 0
sleep 1
sudo reboot 1 > /dev /null 2 > & 1   
}
 
#还原操作系统
function restoreSys
{
touch /tmp /tmpfile
total = `sudo cat /backup /osTotal `
sudo mkfs -t ext4 /dev /sda2 1 > /dev /null 2 > & 1
sudo tune2fs -c - 1 -i 0 /dev /sda2 1 > /dev /null 2 > & 1
#sudo tune2fs -U fb188b20-6b64-4623-8105-bf9281decc85 /dev/sda2 1>/dev/null 2>&1
sudo mount -o rw /dev /sda2 /mnt 1 > /dev /null 2 > & 1
#sudo rm -rf /mnt/*
sudo tar -xpzvf /backup /os.tgz   -C /mnt --touch > /tmp /tmpfile &
#sudo tar -xpzvf /backup/os.tgz  -C /mnt > /tmp/tmpfile &
cur = 0
PCT = 0
end = ` ps -ef   |grep "tar -xpzvf" |wc -l `
(
#while test $total != $cur
while test $end != 1
do
cat <<EOF
XXX
$PCT
It will take a few minutes. Do not press : Ctrl + C.\n\n
Restoring file :\n `tail -n 1 /tmp /tmpfile `
XXX
EOF
cur = `sudo cat /tmp /tmpfile |wc -l `
PCT = ` echo "$cur*100/$total" |bc `
end = ` ps -ef   |grep "tar -xpzvf" |wc -l `
sleep 0. 1
done
) |
dialog --title "Restore System" "$@" --gauge "It will take a few minutes.\nDo not press: Ctrl + C " 12 80 0     
sudo mkdir /mnt /tmp
sudo chmod 777 -R /mnt /tmp
sudo chmod 777 -R /mnt /var /lib /lightdm /
sudo umount /mnt 1 > /dev /null 2 > & 1
#(dialog --title "Restore System" --gauge "Restore finished.\nWill reboot... " 12 80 100) | 0
sleep 1
sudo reboot 1 > /dev /null 2 > & 1   
}
 
#还原应用程序
function restoreApp
{
touch /tmp /tmpfile
sudo mount -o rw /dev /sda3 /mnt 1 > /dev /null 2 > & 1
total = `sudo tar tf /backup /bin.tgz |wc -l `
sudo tar -xpzvf /backup /bin.tgz   -C /mnt   --touch > /tmp /tmpfile &
cur = 0
PCT = 0
end = ` ps -ef   |grep "tar -xpzvf" |wc -l `
(
#while test $total != $cur
while test $end != 1
do
cat <<EOF
XXX
$PCT
It will take a few minutes. Do not press : Ctrl + C.\n\n
Restoring file :\n `tail -n 1 /tmp /tmpfile `
XXX
EOF
cur = `sudo cat /tmp /tmpfile |wc -l `
PCT = ` echo "$cur*100/$total" |bc `
end = ` ps -ef   |grep "tar -xpzvf" |wc -l `
sleep 0. 1
done
) |
dialog --title "Restore Application" "$@" --gauge "It will take a few minutes.\nDo not press: Ctrl + C " 12 80 0     
sudo chmod 777 /mnt /xds 1 > /dev /null 2 > & 1
sudo umount /mnt 1 > /dev /null 2 > & 1      
#(dialog --title "Restore Application" --gauge "Restore finished.\nWill reboot... " 12 80 100) | test 1=1
sleep 1
sudo reboot 1 > /dev /null 2 > & 1   
}
 
#取得GRUB引导菜单的参数
cmd =$( cat /proc /cmdline)
#echo -e $cmd
 
sudo chmod +w /boot /grub /grub.cfg
sudo cp /boot /grub /grub_normal.cfg /boot /grub /grub.cfg
sudo chmod -w /boot /grub /grub.cfg
 
#根据取得的参数进行对应的操作
if echo $cmd | grep -q "backupSys"
then backupSys
elif echo $cmd | grep -q "backupApp"
then backupApp
elif echo $cmd | grep -q "restoreSys"
then restoreSys
elif echo $cmd | grep -q "restoreApp"
then restoreApp
fi
 
#backupDs
加上可执行权限
sudo chmod 777 /etc /init.d /xds.rc
 
3.4 把脚本加入开机自动运行的配置文件中
echo ". /etc/init.d/xds.rc" > ~ /.profile
 
3.5 加入自动登录
    ubuntu 12.04在命令行模式下,默认需要手动输入用户名密码才能登录。需要使用mingetty进行自动登录。
    安装mingetty。
sudo apt -get install mingetty
    配置mingetty的配置文件/etc/init/tty1.conf,注释掉原来的exec,加上一新的,如下:
#exec /sbin/getty -8 38400 tty1
exec /sbin /mingetty --autologin xds tty1
 
 
    至此,Linux备份还原双系统制作完成。一旦系统崩溃或出现不稳定现象,用户只需要接上键盘,在开机时按住shift键,就可以执行系统还原操作。
 
    在上面的基础上,还可以扩展一个功能:通过网络远程进行备份还原。将在下一篇【Linux备份还原双系统设计与实现<二>】进行介绍。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值