yhkylin-backup-tools/backup-daemon/data/backup-auto

1054 lines
31 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
#Author Buquan Liu, liubuquan@kylinos.cn, walt_lbq@163.com
#本程序本质上是对backup-auto/autobackup.cpp的重写.
#因为采用Qt程序则打包进入内核相应的库会导致内核超过16M故改为shell程序.
#backup-auto --autobackup ${rootpath} /backup
#backup-auto --autorestore ${rootpath} /backup
#xgs备份还原要保留更多的文件或目录:
#kybackup/maindialog.cpp, backup-daemon/mountpoint.cpp, backup-daemon/data/backup-auto-efi
XGS=false
INFO="/etc/.bootinfo"
METAINFO=".METAINFO"
KB=1024
MB=1048576
GB=1073741824
if [ $# -lt 3 ] ; then
exit
fi
#是否有/data数据分区
hasDataPartition=0
backupORrestore=$1
rootpath=$2
m_mountPath=$3
BACKUP=
if [[ -e "${rootpath}/backup/BACKUP/snapshots" ]]; then
BACKUP="/BACKUP"
fi
m_backuplistPath=${m_mountPath}${BACKUP}"/snapshots/backuplist.xml"
EXCLUDEFILE=${m_mountPath}${BACKUP}"/snapshots/.exclude"
PLOGFILEDIR="${m_mountPath}${BACKUP}/log"
PLOGFILE="$PLOGFILEDIR/log-$(date +%Y%m%d%H%M)"
LOGFILE="/backup"${BACKUP}"/log.txt" #LOGFILE="/tmp/log.txt"
#是否是出厂备份
m_isFactory=false
factory_uuid="00000000-0000-0000-0000-000000000000"
auto_uuid="01234567-0123-0123-0123-0123456789ab"
PERSONAL_EXCLUDEFILE=".exclude.user.txt"
PERSONAL_BACKUPFILE=".user.txt"
#如果/backup不存在则创建该目录
mkdir -p ${m_mountPath}${BACKUP}
m_restoreUuid=""
m_enabled=""
global_system_usedDisk=0
m_size=0
newSize=0
#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
getBackupInfo(){
if [ "$rootpath" = "/" ]; then
bootinfo=$INFO
else
bootinfo=$rootpath$INFO
fi
if [ ! -e "$bootinfo" ]; then
echo "$bootinfo file not exist!"
exit 200
fi
which_line=0
content=`cat "$bootinfo" | grep -Ev "^#" | grep "=" | awk '{print $1}'`
for line in $content;
do
#parse_device "$device"
#只读第1行RECOVERY_DEV_UUID=c965e712-9903-4139-b8da-c6e1eef0af6a
if [ $which_line -eq 0 ]; then
m_restoreUuid=`echo $line | sed 's:.*=::' | tr -d "\n"`
which_line=`expr $which_line + 1`
else
m_enabled=`echo $line | sed 's:.*=::' | tr -d "\n"`
which_line=`expr $which_line + 1`
fi
done
}
#-----------------------------------------------------------------
#该函数是对backup-daemon/parsebackuplist.cpp中相应函数的替换
createBackupList(){
local backuplistDir=${m_mountPath}${BACKUP}"/snapshots/"
if [ ! -e "$backuplistDir" ]; then
mkdir -p $backuplistDir
fi
if [ ! -e "$m_backuplistPath" ]; then
#echo "$m_backuplistPath file not exist!"
#第1行'>'会清空后写文件
echo "<?xml version='1.0'?>" >$m_backuplistPath
#echo "<backupList>" >>$m_backuplistPath
#echo "</backupList>" >>$m_backuplistPath
echo "<backupList/>" >>$m_backuplistPath #QDomDocument在节点为空时如此生成根节点
fi
}
#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
mountBackup()
{
local myuuid="/dev/disk/by-uuid/"$m_restoreUuid
#echo "myuuid: $myuuid"
#support lvm by zhangze
tmp_root_dev=$(mount|grep " /root "| cut -d ' ' -f 1)
case "$tmp_root_dev" in
/dev/mapper/*)
eval $(dmsetup splitname --nameprefixes --noheadings --rows "${tmp_root_dev#/dev/mapper/}")
if [ "$DM_VG_NAME" ] && [ "$DM_LV_NAME" ];then
lvm lvchange -aay -y --sysinit --ignoreskippedcluster "$DM_VG_NAME"
fi
;;
esac
mount $myuuid $m_mountPath
mkdir -p $PLOGFILEDIR
if [ $? -ne 0 ]; then
echo "Could not create log directory in /backup"
exit 22
fi
touch $PLOGFILE
if [ $? -ne 0 ]; then
echo "Could not create log file"
exit 23
fi
echo "Log for backuping and restoring...." >$PLOGFILE
createBackupList #创建备份信息
}
#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
umountBackup()
{
umount $m_mountPath
}
#-----------------------------------------------------------------
#see backup-auto/backupcommon.cpp
#在grub时根分区为/root在进入系统后根分区为/
#parameters: rootDiskName
#返回值 elements=( $totalSize $freeDisk $usedDisk )
caculateDiskSize(){
local origalParas
origalParas=(`echo "$@"`)
num=$[ $# ]
#if [ $# -ne 2 ]; then
if [ $num -ne 2 ]; then
echo "You shoud input the rootDiskName and disk"
exit
fi
local fullDiskName
local totalSize
local freeDisk
local usedDisk
if [ "${origalParas[1]}" = "/" ]; then
fullDiskName=${origalParas[0]}
else
fullDiskName=${origalParas[0]}${origalParas[1]}
fi
if [ ! -e "$fullDiskName" ]; then
##因为要返回数组所以下面的echo没有上面用不会显示只会作为返回值
#echo "$fullDiskName not exist!"
elements=( 0 0 0 )
echo ${elements[*]}
return
fi
##因为要返回数组这里不能echo "fullDiskName: $fullDiskName"
sss=`df -k $fullDiskName | sed '1d' | tr -d "\n"`
freeDisk=`echo $sss|awk '{print $4}'`
freeDisk=`expr 1024 \* $freeDisk`
usedDisk=`echo $sss|awk '{print $3}'`
usedDisk=`expr 1024 \* $usedDisk`
#totalSize没有从df命令的第2列来取该值比下面2个的和还要大
totalSize=`expr $usedDisk + $freeDisk`
##因为要返回数组这里不能echo "freeDisk=$freeDisk"
##因为要返回数组这里不能echo "usedDisk=$usedDisk"
##因为要返回数组这里不能echo "totalSize=$totalSize"
#local elements
elements=( $totalSize $freeDisk $usedDisk )
echo ${elements[*]}
}
parse_device(){
device=$1
if echo $device | grep -E -q "^UUID="; then
echo $device | sed 's:^UUID=:/dev/disk/by-uuid/:' | tr -d "\n"
elif echo $device | grep -E -q "^LABEL="; then
echo $device | sed 's:^LABEL=:/dev/disk/by-label/:' | tr -d "\n"
else
echo $device | tr -d "\n"
fi
}
is_remote(){
fstype=$1
if [ nfs = "$fstype" ] || [ nfs4 = "$fstype" ] || [ smbfs = "$fstype" ] || [ cifs = "$fstype" ] || [ coda = "$fstype" ] || [ ncp = "$fstype" ]; then
echo yes
elif [ ncpfs = "$fstype" ] || [ ocfs2 = "$fstype" ] || [ gfs = "$fstype" ] || [ gfs2 = "$fstype" ] || [ ceph = "$fstype" ]; then
echo yes
else
echo no
fi
}
function caculateDirSize() {
mkdir -p /backup/snapshots/check/data
local total_file_size=$(rsync -aAHXrn --stats --ignore-missing-args --exclude=/backup --exclude=/cdrom --exclude=/dev --exclude=/efi --exclude=/etc/uid_list --exclude=/data/ghost --exclude=/ghost --exclude=/lost+found --exclude=/media --exclude=/mnt --exclude=/proc --exclude=/run --exclude=/swap_file --exclude=/sys --exclude=/tmp --exclude=/var/lib/docker/overlay2 --exclude=/var/lib/kmre/data --exclude=/var/lib/kmre/kmre-*-*/data/media/0/0-麒麟* --exclude=/var/lib/udisks2 --exclude=/var/log --exclude=*/backup/snapshots --exclude=/data/home --exclude=/data/root "${rootpath}/" /backup/snapshots/check/data/ | grep "Total file size:" | awk '{print $4}' | sed 's/,//g')
total_file_size=$(expr ${total_file_size} + 200000000)
echo "备份所需空间大小:${total_file_size}" >>$PLOGFILE
echo "${total_file_size}"
}
#parameters: 无
#返回值:(system_totalSize system_freeDisk system_usedDisk)
caculateSystemSize(){
local root_totalSize root_freeDisk root_usedDisk
local system_totalSize system_freeDisk system_usedDisk
local origalParas
local found item result
local device mntdir fstype options dump passno
local -a alreadyDisks #数组,已经分析过的磁盘目录
local -a elements #存放返回值
#alreadyDisks=(${alreadyDisks[*]} "/boot") #插入一个元素"/boot"
#result=(`caculateDiskSize "$rootpath" "$rootpath"`)
#origalParas=($rootpath "/")
#arg1=`echo ${origalParas[*]}`
#result=(`caculateDiskSize $arg1`)
#root_totalSize=${result[0]}
#root_freeDisk=${result[1]}
#root_usedDisk=${result[2]}
#system_totalSize=$root_totalSize
#system_freeDisk=$root_freeDisk
#system_usedDisk=$root_usedDisk
#echo "system_totalSize="$system_totalSize
#echo "system_freeDisk="$system_freeDisk
#echo "system_usedDisk="$system_usedDisk
##############3#caculateDiskSize / /backup
fstab_path=${rootpath}/etc/fstab
if [ ! -e "$fstab_path" ]; then
echo "$fstab_path file not exist!"
exit 701
fi
system_totalSize=0
system_freeDisk=0
system_usedDisk=0
while read line;
do
#取第1个字符
if [ "${line:0:1}" = "#" ]; then
continue
fi
echo $line
echo $line >>$PLOGFILE
device=$( echo "$line"|awk '{print $1}')
mntdir=$( echo "$line"|awk '{print $2}')
fstype=$( echo "$line"|awk '{print $3}')
options=$( echo "$line"|awk '{print $4}')
dump=$( echo "$line"|awk '{print $5}')
passno=$( echo "$line"|awk '{print $6}')
device=$(parse_device $device)
if [[ $options =~ "bind" ]]; then
continue
fi
# nodev filesystems
( cat /proc/filesystems | grep "$fstype" | grep -q nodev ) && continue
# virtual or network filesystems
[ none = "$mntdir" ] || [ yes = $(is_remote $fstype) ] && continue
# swap or rootfs
[ swap = "$fstype" ] && continue
#[ swap = "$fstype" ] || [ / = "$mntdir" ] || [ /home = "$mntdir" ] || [ /var/log = "$mntdir" ]&& continue
#取第1个字符
if [ ${mntdir:0:1} != "/" ]; then
continue
fi
if [ $mntdir = "/backup" ]; then #没有写成$m_mountPath,看下面if
continue
fi
if [ $mntdir = $m_mountPath ]; then #没有写成$m_mountPath
continue
fi
#注意: 没有备份数据分区
if [ $mntdir = "/data" ]; then
hasDataPartition=1
fi
#echo "1: " $device
#echo "2: " $mntdir
#echo "3: " $fstype
#echo "4: " $options
#echo "5: " $dump
#echo "6: " $passno
# not system partition
# [ no = $(is_system_partition $mntdir) ] && continue
################计算df $target_mntdir的各项值
origalParas=($rootpath $mntdir)
arg1=`echo ${origalParas[*]}`
result=(`caculateDiskSize $arg1`)
disk_totalSize=${result[0]}
disk_freeDisk=${result[1]}
disk_usedDisk=${result[2]}
if [[ $disk_totalSize = $root_totalSize && $disk_freeDisk = $root_freeDisk && $disk_usedDisk = $root_usedDisk ]]; then
continue
fi
#echo "disk_totalSize="$disk_totalSize
#echo "disk_freeDisk="$disk_freeDisk
#echo "disk_usedDisk="$disk_usedDisk
system_totalSize=$( expr $system_totalSize + $disk_totalSize )
system_freeDisk=$( expr $system_freeDisk + $disk_freeDisk )
system_usedDisk=$( expr $system_usedDisk + $disk_usedDisk )
#echo "system_totalSize="$system_totalSize
#echo "system_freeDisk="$system_freeDisk
#echo "system_usedDisk="$system_usedDisk
done < "$fstab_path";
#echo "system_totalSize="$system_totalSize
#echo "system_freeDisk="$system_freeDisk
#echo "system_usedDisk="$system_usedDisk
#local elements
elements=( $system_totalSize $system_freeDisk $system_usedDisk )
echo ${elements[*]}
}
#-----------------------------------------------------------------
#//检查备份还原分区/backup剩余空间是否满足备份需求
#see backup-auto/backupcommon.cpp
#返回值: 0表示/backup剩余容量不能够满足备份需求1表示满足
checkBackupCapacity() { #(m_rootPath.toStdString().c_str(), retstatus))
local origalParas
local root_totalSize root_freeDisk root_usedDisk
local backup_totalSize backup_freeDisk backup_usedDisk
local system_totalSize system_freeDisk system_usedDisk
###which_line=`expr $which_line + 1`
#从函数caculateSystemSize取返回值
result=(`caculateSystemSize`)
system_totalSize=${result[0]}
system_freeDisk=${result[1]}
system_usedDisk=${result[2]}
#global_system_usedDisk=$system_usedDisk
global_system_usedDisk=$(caculateDirSize)
#echo "--system_totalSize="$system_totalSize
#echo "--system_freeDisk="$system_freeDisk
#echo "--system_usedDisk="$system_usedDisk
#--------------------------------------------------------
#result=(`caculateDiskSize "$rootpath" "$rootpath"`)
origalParas=($rootpath "/")
arg1=`echo ${origalParas[*]}`
result=(`caculateDiskSize $arg1`)
root_totalSize=${result[0]}
root_freeDisk=${result[1]}
root_usedDisk=${result[2]}
#echo "--root_totalSize="$root_totalSize
#echo "--root_freeDisk="$root_freeDisk
#echo "--root_usedDisk="$root_usedDisk
#--------------------------------------------------------
#caculateDiskSize / /backup
#origalParas=($rootpath "/backup")
#origalParas=("/" "/backup") #/backup不会是/root/backup
origalParas=("/" $m_mountPath) #/backup不会是/root/backup
arg1=`echo ${origalParas[*]}`
result=(`caculateDiskSize $arg1`)
backup_totalSize=${result[0]}
backup_freeDisk=${result[1]}
backup_usedDisk=${result[2]}
#echo "--backup_totalSize="$backup_totalSize
#echo "--backup_freeDisk="$backup_freeDisk
#echo "--backup_usedDisk="$backup_usedDisk
if [[ $root_totalSize = $backup_totalSize && $root_freeDisk = $backup_freeDisk && $root_usedDisk = $backup_usedDisk ]]; then #"/backup"是不是一个独立的盘
echo "Cannot find the /backup disk or not be mounted!"
exit 403
fi
#echo "bybobbi: bakup_freeDisk is " $backup_freeDisk
#echo "bybobbi: system_usedDisk is " $system_usedDisk
echo "free size : $backup_freeDisk; sys_size : $global_system_usedDisk"
echo "free size : $backup_freeDisk; sys_size : $global_system_usedDisk" >>$PLOGFILE
if [ ${backup_freeDisk} -gt ${global_system_usedDisk} ]; then
return 1
else
return 0
fi
}
updateStateByComment() {
tmpFile=${m_backuplistPath}".tmp"
#echo "tmpFile: $tmpFile"
is_first_line=1
foundComment=0 #是否发现了要修改的comment
#如果不定义IFS则echo $line会去掉前后空格导致写到文件中去时没有格式
IFS_old=$IFS
IFS=$'\n'
while read line;
do
#去除了前后空格
xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
#echo "xxx: $xxx"
if [[ "$xxx" =~ "<Comment>" ]]; then
if [ $xxx = "<Comment>${m_comment}</Comment>" ]; then
foundComment=1 #当前comment是要修改的mycomment
else
foundComment=0 #当前comment不是要修改的mycomment
fi
fi
if [[ "$xxx" =~ "<Size>" ]]; then
if [[ $foundComment -eq 1 ]]; then
line=" <Size>${newSize}</Size>"
fi
fi
if [[ "$xxx" =~ "<State>" ]]; then
if [ $foundComment -eq 1 ]; then
line=" <State>${m_state}</State>"
fi
fi
if [ "$is_first_line" -eq 1 ]; then
echo "$line" >$tmpFile
else
echo "$line" >>$tmpFile
fi
is_first_line=0
done < "$m_backuplistPath";
IFS=$IFS_old
cp -f $tmpFile ${m_backuplistPath}
rm -f $tmpFile
}
#参照backup-daemon/backupmanager.cpp, 写日志文件
writeLogFile() {
echo $1 >>$LOGFILE
}
#参照backup-daemon/mountpoint.cpp
bFileExists() {
local theFile theOldFile
theOldFile=$1 #必须以"/"开始但本身是个相对路径因为没有加rootpath.
if [ $rootpath = "/" ]; then
theFile=$theOldFile
else
theFile=$theOldFile
theFile="$rootpath""$theFile"
fi
if [ -e "$theFile" ]; then
echo "$theOldFile" >>$EXCLUDEFILE
fi
}
#参照backup-daemon/mountpoint.cpp
generateExcludeFile() {
local backupOrRestore
backupOrRestore=$1 #0: backup 1:restore
#exclude的必须是相对目录其实在efi启动时为/root/data
#see backup-daemon/mountpoint.cpp, backup-daemon/data/backup-auto-efi
#also kybackup: exclude.ui databackupdirs.ui dataincbackupdirs.ui
#if [ ! -e "$restoreDir" ]; then
#注意下面的>和>>-----------------------------------------------
echo "/efi" >$EXCLUDEFILE
echo "/backup" >>$EXCLUDEFILE
#echo "/boot/efi" >>$EXCLUDEFILE
echo "/dev" >>$EXCLUDEFILE
echo "/ghost" >>$EXCLUDEFILE #ghost镜像文件
echo "/mnt" >>$EXCLUDEFILE
echo "/proc" >>$EXCLUDEFILE
echo "/run" >>$EXCLUDEFILE
echo "/sys" >>$EXCLUDEFILE
echo "/media" >>$EXCLUDEFILE
echo "/tmp" >>$EXCLUDEFILE
echo "/lost+found" >>$EXCLUDEFILE
echo "/var/lib/udisks2" >>$EXCLUDEFILE
#echo "/data/home/*" >>$EXCLUDEFILE
#echo "/data/root/*" >>$EXCLUDEFILE
#if [ -e "${rootpath}/data/home" ]; then
# echo "/home" >>$EXCLUDEFILE
# echo "/root" >>$EXCLUDEFILE
#fi
echo "/cdrom" >>$EXCLUDEFILE
echo "/swap_file" >>$EXCLUDEFILE
echo "/var/lib/docker/overlay2" >>$EXCLUDEFILE
echo "/var/log" >>$EXCLUDEFILE
#bind挂载的目录不进行备份或还原
cat ${rootpath}/etc/fstab | awk '{if($4~/bind/) print $1}' |
while read excludePath
do
echo "$excludePath" >>$EXCLUDEFILE
done
#bFileExists "/etc/.bootinfo"
#bFileExists "/etc/fpb" #管控,暂时
#echo "/etc/.bootinfo" >>$EXCLUDEFILE
#数据分区是否使用由用户输入,最终放到/backup/snapshots/.excludeuser
#因为GRUB没有界面所以是不是先在其他模式下做一次备份生成这个文件然后GRUB就可以了。
#echo "/data/*" >>$EXCLUDEFILE #用户可以把数据放到该分区或者目录
#是否覆盖备份还原工具自身
#if [ $backupOrRestore -eq 1 ]; then
# bFileExists "/usr/bin/backup-daemon" #备份还原
# bFileExists "/usr/bin/kybackup" #备份还原
# bFileExists "/usr/bin/mount_fstab" #备份还原
# bFileExists "/usr/bin/backup-auto" #备份还原
# bFileExists "/usr/bin/mount_fstab_efi" #备份还原
# bFileExists "/usr/bin/backup-auto-efi" #备份还原
#fi
#是否使用由用户输入,最终放到/backup/snapshots/.excludeuser
#if [ "$XGS" = true ]; then
# echo "/etc/passwd" >>$EXCLUDEFILE
# echo "/etc/group" >>$EXCLUDEFILE
# echo "/etc/shadow" >>$EXCLUDEFILE
# if [ -e "/etc/uid_list" ]; then
# echo "/etc/uid_list" >>$EXCLUDEFILE
# fi
# echo "/home/*" >>$EXCLUDEFILE
# echo "/opt/softmanager/log/log_cur.txt" >>$EXCLUDEFILE
# echo "/opt/softmanager/conf/audit/auditLogCur.txt" >>$EXCLUDEFILE
# echo "/opt/xgs/Audit/*" >>$EXCLUDEFILE
# echo "/opt/LinuxKpc/log/*" >>$EXCLUDEFILE
# echo "/var/log/*" >>$EXCLUDEFILE
# echo "/var/run/*" >>$EXCLUDEFILE
# echo "/root/*" >>$EXCLUDEFILE
# echo "/var/mail/*" >>$EXCLUDEFILE
# echo "/boot/efi/*" >>$EXCLUDEFILE #xgs出厂还原时会失败
#fi
#fi
}
backuping() {
local src dst
src=$1
dst=$2
#0:backup 1:restore
generateExcludeFile 0
echo "/" > ${m_mountPath}${BACKUP}/snapshots/$m_uuid/$PERSONAL_BACKUPFILE
cp $EXCLUDEFILE ${m_mountPath}${BACKUP}/snapshots/$m_uuid/$PERSONAL_EXCLUDEFILE
# /boot/efi不再单独备份
#if [ -d ${src}/boot/efi ];then
# mkdir -p ${dst}/boot
# rsync -av --ignore-missing-args ${src}/boot/efi ${dst}/boot
#fi
echo "Begin to backup..." >>$PLOGFILE
echo "Begin to backup..."
mkdir -p ${rootpath}/var/log
touch ${rootpath}/var/log/backup.log
#是否有数据分区
if [ $hasDataPartition -eq 0 ]; then
#exclude的必须是相对目录其实在efi启动时为/root/data
#echo rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst
#rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst
#不是目录,也不备份
echo rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >>${rootpath}/var/log/backup.log 2>&1
rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >>${rootpath}/var/log/backup.log 2>&1
else
#exclude的必须是相对目录其实在efi启动时为/root/data
#echo rsync -avAXH --ignore-missing-args --exclude data --exclude-from=$EXCLUDEFILE $src $dst
#The question is that the 'data' directories can not be copied
echo rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >>${rootpath}/var/log/backup.log 2>&1
rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >>${rootpath}/var/log/backup.log 2>&1
fi
if [ $? -eq 0 -o $? -eq 24 -o $? -eq 23 ]; then
#将状态从"备份未完成"改成"0"
#updateStateByComment $m_comment 0
m_state="backup finished"
touch $dst/.exectl
updateStateByComment
else
echo "backup update backuplist.xml failed for updateBackupAutoFinishedState!";
m_state="backup unfinished"
updateStateByComment
fi
#写文件
metainfo_file="${m_mountPath}${BACKUP}/snapshots/$m_uuid/$METAINFO"
#echo "metainfo_file="$metainfo_file
#第1行清空写
#这里写的不是xml文件是一个文本文件这时候的状态是0或者backup failed
echo "COMMENT=$m_comment" >$metainfo_file
echo "TIME=$m_time" >>$metainfo_file
echo "UUID=$m_uuid" >>$metainfo_file
echo "SIZE=$m_size" >>$metainfo_file
echo "STATE=$m_state" >>$metainfo_file
#写日志文件
writeLogFile "${m_time},${m_uuid},0,出厂备份,${newSize}" #grub时只有全盘备份没有增量备份
echo "sync..." >>$PLOGFILE
sync
echo "Backup end..." >>$PLOGFILE
}
CreateUuid() {
local uuid=`cat /proc/sys/kernel/random/uuid|tr -d "\n"`
while [ "$uuid" = $factory_uuid -o "$uuid" = $auto_uuid ]
do
uuid=`cat /proc/sys/kernel/random/uuid|tr -d "\n"`
done
echo $uuid
}
findCommentByUuid() {
local ret=1
local local_uuid=$1
local comment0
local ret_comment
#如果不定义IFS则echo $line会去掉前后空格导致写到文件中去时没有格式
IFS_old=$IFS
IFS=$'\n'
while read line;
do
#去除了前后空格
xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
#echo "xxx: $xxx"
if [[ "$xxx" =~ "<Comment>" ]]; then
comment0=`echo $xxx | awk -F "<Comment>" '{print $2}' |awk -F "</Comment>" '{print $1}' | tr -d "\n"`
fi
if [[ "$xxx" =~ "<Uuid>" ]]; then
if [ $xxx = "<Uuid>${local_uuid}</Uuid>" ]; then
ret=0
ret_comment=$comment0
break
fi
fi
done < "$m_backuplistPath";
IFS=$IFS_old
echo $ret_comment
return $ret
}
deleteItemByComment() {
local local_comment=$1
# echo "arg local_comment = $local_comment"
tmpFile=${m_backuplistPath}".tmp"
cp -f ${m_backuplistPath} $tmpFile
# echo "tmpFile: $tmpFile"
local foundComment=0 #是否发现了要修改的comment
local i=0
local ii=0
local iii=0
local backupPointTmp=0
#如果不定义IFS则echo $line会去掉前后空格导致写到文件中去时没有格式
IFS_old=$IFS
IFS=$'\n'
while read line;
do
let i+=1
#去除了前后空格
xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
#echo "xxx: $xxx"
if [[ "$xxx" =~ "<BackupPoint>" ]]; then
backupPointTmp=$i
fi
if [[ "$xxx" =~ "<Comment>" ]]; then
if [ $xxx = "<Comment>$local_comment</Comment>" ]; then
foundComment=1 #当前comment是要修改的mycomment
ii=$backupPointTmp
# echo "delete foundComment = 1"
else
foundComment=0 #当前comment不是要修改的mycomment
fi
fi
if [[ "$xxx" =~ "</BackupPoint>" ]]; then
if [ $foundComment -eq 1 ]; then
iii=$i
break
fi
fi
done < "$tmpFile";
IFS=$IFS_old
# echo "ii: $ii, iii: $iii"
if [ $iii -ne 0 ]; then
sed -i "${ii},${iii}d" $tmpFile
cp -f $tmpFile ${m_backuplistPath}
fi
rm -f $tmpFile
}
DeleteFactoryBackup() {
if [ -e "/backup${BACKUP}/snapshots/{${factory_uuid}}" ]; then
rm /backup${BACKUP}/snapshots/{${factory_uuid}} -rf
fi
local comment=$(findCommentByUuid "{${factory_uuid}}")
echo "DeleteFactoryBackup comment is $comment"
if [ $? -eq 0 ]; then
deleteItemByComment "$comment"
fi
}
#see backup-auto/autobackup.cpp
backupAuto() { #备份
if [ $m_isFactory = true ]; then
DeleteFactoryBackup
fi
local xxx
checkBackupCapacity
ret=$?
if [ "$ret" -eq 0 ]; then
echo "The backup disk space is not enough"
exit 100
fi
#global_system_usedDisk
#创建一个uuid
if [ $m_isFactory = false ]; then
m_uuid=$(CreateUuid)
else
m_uuid="$factory_uuid"
fi
m_uuid="{"${m_uuid}"}"
echo "BYbobbi: m_uuid is $m_uuid"
m_time=`date "+%y-%m-%d %H:%M:%S"|tr -d "\n"`
m_comment=$m_time #这个是全局变量
dst="${m_mountPath}${BACKUP}/snapshots/${m_uuid}/data"
#echo "dst: $dst"
mkdir -p $dst
m_size=$global_system_usedDisk
#m_size=188248
newSize1=$( echo "scale=2;$m_size / $GB"|bc)
newSize2=$( echo "scale=2;$m_size / $MB"|bc)
newSize3=$( echo "scale=2;$m_size / $KB"|bc)
if [ $( echo "$newSize1 > 1.0"|bc ) = 1 ]; then
newSize=$newSize1"GB"
elif [ $( echo "$newSize2 > 1.0"|bc ) = 1 ]; then
newSize=$newSize2"MB"
else
newSize=$newSize3"KB"
fi
state="backup unfinished"
#写入文件m_backuplistPath=$m_mountPath"/snapshots/backuplist1.xml"
#bool AutoBackup::backupAuto()251 if (!m_parse->addItem(m_comment, time, m_uuid, newsize, "backup unfinished")) {
#
tmpFile=${m_backuplistPath}".tmp"
#echo "tmpFile: $tmpFile"
new_content=""
is_first_line=1
hasHead=false #有头吗"<backupList>"
#如果不定义IFS则echo $line会去掉前后空格导致写到文件中去时没有格式
IFS_old=$IFS
IFS=$'\n'
while read line;
do
#去除了前后空格
xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
#echo "xxx: $xxx"
if [[ "$xxx" =~ "<backupList>" ]]; then
hasHead=true
fi
if [[ "$xxx" =~ "<backupList/>" ]]; then
xxx="</backupList>" #与图形界面一致
line="</backupList>"
fi
#插入新的记录
if [ $xxx = "</backupList>" ]; then
if [ "$hasHead" = false ]; then
echo "<backupList>" >>$tmpFile
hasHead=true
fi
echo " <BackupPoint>" >>$tmpFile
echo " <Comment>$m_comment</Comment>" >>$tmpFile
echo " <Time>$m_time</Time>" >>$tmpFile
echo " <Uuid>$m_uuid</Uuid>" >>$tmpFile
echo " <Size>$newSize</Size>" >>$tmpFile
echo " <State>$state</State>" >>$tmpFile
echo " <Type>0</Type>" >>$tmpFile
echo " </BackupPoint>" >>$tmpFile
fi
if [ "$is_first_line" -eq 1 ]; then
echo "$line" >$tmpFile
else
echo "$line" >>$tmpFile
fi
is_first_line=0
done < "$m_backuplistPath";
IFS=$IFS_old
cp -f $tmpFile ${m_backuplistPath}
rm -f $tmpFile
#写文件
metainfo_file="${m_mountPath}${BACKUP}/snapshots/$m_uuid/$METAINFO"
#echo "metainfo_file="$metainfo_file
#第1行清空写
#这里写的不是xml文件是一个文本文件这时候的状态是backup unfinished
echo "COMMENT=$m_comment" >$metainfo_file
echo "TIME=$m_time" >>$metainfo_file
echo "UUID=$m_uuid" >>$metainfo_file
echo "SIZE=$m_size" >>$metainfo_file
echo "STATE=$state" >>$metainfo_file
echo "TYPE=0" >>$metainfo_file
backuping ${rootpath}/ $dst
}
#返回值:
getLastUsefulBackupPointUuid() {
local xxx currentUuid foundComment
currentUuid=""
currentState=false
currentType=true
lastUsefulBackupPointUuid=""
foundComment=0 #是否发现了要修改的comment
#如果不定义IFS则echo $line会去掉前后空格导致写到文件中去时没有格式
IFS_old=$IFS
IFS=$'\n'
while read line;
do
#去除了前后空格
xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
#echo "xxx: $xxx"
if [[ "$xxx" =~ "<Uuid>" ]]; then
currentUuid=$xxx
currentState=false
currentType=true
fi
if [[ "$xxx" =~ "<State>backup finished</State>" ]]; then
#lastUsefulBackupPointUuid=$currentUuid
currentState=true
fi
if [[ "$xxx" =~ "<Type>2</Type>" ]]; then
currentType=false
fi
if [[ "$xxx" =~ "<Type>3</Type>" ]]; then
currentType=false
fi
if [[ "$xxx" =~ "</BackupPoint>" ]]; then
if [ "$currentState" = true -a "$currentType" = true ]; then #"/backup"是不是一个独立的盘
lastUsefulBackupPointUuid=$currentUuid
fi
fi
done < "$m_backuplistPath";
IFS=$IFS_old
if [ "$lastUsefulBackupPointUuid" = "" ]; then
echo "can't find a useful backup for restoring"
exit 300
fi
lastUsefulBackupPointUuid=`echo $lastUsefulBackupPointUuid | sed 's:<Uuid>::' | tr -d "\n"`
lastUsefulBackupPointUuid=`echo $lastUsefulBackupPointUuid | sed 's:</Uuid>.*::' | tr -d "\n"`
#echo "lastUsefulBackupPointUuid=$lastUsefulBackupPointUuid"
}
#see backup-auto/autobackup.cpp
restoreAuto() { #还原
local xxx
getLastUsefulBackupPointUuid
#echo "lastUsefulBackupPointUuid=$lastUsefulBackupPointUuid"
#写日志文件
local m_time=`date "+%y-%m-%d %H:%M:%S"|tr -d "\n"`
writeLogFile "${m_time},${lastUsefulBackupPointUuid},4,grub系统还原" #grub时只有一键还原没有增量还原
restoreDir="${m_mountPath}${BACKUP}/snapshots/$lastUsefulBackupPointUuid"
if [ ! -e "$restoreDir" ]; then
echo "full restore directory not exists!"
exit 301 #备份文件不存在,不能还原系统
fi
#0:backup 1:restore
generateExcludeFile 1
if [ -d "${restoreDir}/data/efi" ];then
mkdir -p ${rootpath}/boot
rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete ${restoreDir}/data/efi ${rootpath}/boot
elif [ -d "${restoreDir}/data/boot/efi" ];then
mkdir -p ${rootpath}/boot
rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete ${restoreDir}/data/boot/efi ${rootpath}/boot
fi
#yi jian huan yuan
if [ ! -e "$restoreDir/data/data" ]; then
#这两行要一致
echo "rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --exclude /data --exclude-from $restoreDir/$PERSONAL_EXCLUDEFILE $restoreDir/data/ $rootpath >/dev/null 2>${rootpath}/var/log/backup.log"
rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --exclude /data --exclude-from $restoreDir/$PERSONAL_EXCLUDEFILE $restoreDir/data/ $rootpath >/dev/null 2>${rootpath}/var/log/backup.log
else
#这两行要一致
echo "rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --exclude-from $restoreDir/$PERSONAL_EXCLUDEFILE $restoreDir/data/ $rootpath >/dev/null 2>${rootpath}/var/log/backup.log"
rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --exclude-from $restoreDir/$PERSONAL_EXCLUDEFILE $restoreDir/data/ $rootpath >/dev/null 2>${rootpath}/var/log/backup.log
fi
if [ $? -ne 0 -a $? -ne 24 -a $? -ne 23 ]; then
echo "full restore process finished failed!"
exit 303
fi
#还原时清空目录
#if [ -e "$rootpath/home/data" ]; then
# rm -r "$rootpath/home/data" ]
#fi
#mkdir -p "$rootpath/home/data" ]
}
#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
updateBackupAutoFinishedState() {
echo "this is updateBackupAutoFinishedState"
}
#-----------------------------------------------------------------
#--------主程序从这里开始-----------------------------------------
if [ "${rootpath}" = "/" ]; then
echo "This program is used in boot time"
# exit
fi
getBackupInfo
#echo "m_restoreUuid="$m_restoreUuid
#echo "m_enabled="$m_enabled
#不加引号报错
if [ "$m_restoreUuid" = "" ] || [ "$m_enabled" = "" ]; then
echo "bootinfo file is not correct!"
exit 202
fi
if [ $backupORrestore = "--autobackup" ]; then
mountBackup
backupAuto #备份, grub时只有全盘备份没有增量备份
updateBackupAutoFinishedState
#umountBackup
echo "This is autobackup"
elif [ $backupORrestore = "--autorestore" ]; then
mountBackup
restoreAuto #还原, grub时只有一键还原没有增量还原
#umountBackup
echo "This is autorestore"
elif [ $backupORrestore = "--factorybackup" ]; then
m_isFactory=true
mountBackup
mount >>$PLOGFILE
backupAuto #备份, grub时只有全盘备份没有增量备份
updateBackupAutoFinishedState
#umountBackup
echo "This is factorybackup"
else
echo "Not correct command"
exit 1
fi
exit 0