LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2143|回复: 17

系统备份脚本

[复制链接]
发表于 2005-1-19 10:33:25 | 显示全部楼层 |阅读模式
我写了一个系统备份的脚本,暂时是个雏形,很多地方仍需改善,请各位多发表意见。谢谢!

使用方法:backup.sh [all | weekly | monthly]
详细内容都写在脚本头部的注释里了。


  1. #!/bin/bash

  2. # This script makes the backup of the system, the config file should be
  3. # in the home directory, called ".backup". The config file should filled
  4. # with several lines of the source pathes which you want to be backed
  5. # up. Each line has to in the format of this: "freq /source/path
  6. # options". the "freq" is the frequency you want this source to be
  7. # backed up, and "options" are the options you want to pass to tar. when
  8. # running this script you can specify the frequency you want to make
  9. # backups this time, for example: "backup.sh weekly". Then the script
  10. # will pick the matching source to backup. Currently there are three
  11. # types of frequency, which are "all", "weekly" and "monthly".
  12. # Written by Neo Anderson
  13. # Jan 18 2005

  14. MTOGGLE=$1
  15. DEST="/mnt/usbc"        # set this to the destination which you want all
  16.                         # the backup files go

  17. initiate() {
  18.         # check if the user is running this script as root
  19.         if [ "$(whoami)" != 'root' ]
  20.         then
  21.                 echo "Please run this script as root!"
  22.                 exit
  23.         fi
  24.         # check the existance of the config file
  25.         if [ ! -f $HOME/.backup -a ! -r $HOME/.backup]
  26.         then
  27.                 echo "Config file not exist or unreadable."
  28.                 exit
  29.         fi
  30.         # check if the destination directory is mounted, if not, ask user
  31.         if [ ! "`cat /etc/mtab | grep $DEST`" ]
  32.         then
  33.                 echo "Device unaccessable. Please mount before backup."
  34.                 echo -n "Mount now? (y/n)"
  35.                 read -n 1 USER_ANS
  36.                 # ask user for response, if yes then mount the
  37.                 # partition, if no then kill the script
  38.                 if [ $USER_ANS == 'y' ]
  39.                 then
  40.                         mount $DEST
  41.                 else
  42.                         echo ""
  43.                         exit
  44.                 fi
  45.         fi
  46.         cd /
  47. }

  48. prebackup() {
  49.         exec 7<&0        # redirect the input to FD 7
  50.         exec < $HOME/.backup        # redirect the input to the file .backup
  51.         while read INPUT        # read the config file line by line
  52.         do
  53.                 # get the frequency
  54.                 TOGGLE="`echo $INPUT | awk '{ print $1 }'`"
  55.                 # get the source path and options passed to tar
  56.                 SOURCE=${INPUT#$TOGGLE}
  57.                 # check the toggle provided by user when running this
  58.                 # script
  59.                 case $MTOGGLE in
  60.                         weekly)
  61.                                 # if the toggle specified by user
  62.                                 # matches the toggle for each source,
  63.                                 # then back it up
  64.                                 if [ $MTOGGLE == $TOGGLE ]
  65.                                 then
  66.                                         backup
  67.                                 else
  68.                                         continue
  69.                                 fi
  70.                                 ;;
  71.                         monthly)
  72.                                 if [ $MTOGGLE == $TOGGLE ]
  73.                                 then
  74.                                         backup
  75.                                 else
  76.                                         continue
  77.                                 fi
  78.                                 ;;
  79.                         all)
  80.                                 backup
  81.                                 ;;
  82.                         *)
  83.                                 usage
  84.                                 exit
  85.                                 ;;
  86.                 esac
  87.         done
  88.         exec 7<&-
  89. }

  90. backup() {
  91.         SOURCE_PATH="`echo $SOURCE | awk '{ print $1 }'`"
  92.         DEST_NAME="$DEST/`basename $SOURCE_PATH`"
  93.         # check if it is the root directory /. If it is, set the name to
  94.         # root, if it is not, work as normal.
  95.         if [ "`basename $SOURCE_PATH`" != '/' ]
  96.         then
  97.                 DEST_TAR="$DEST_NAME."`date +%b%d%Y-%H%M`".tar.gz"
  98.         else
  99.                 DEST_TAR="$DEST/root."`date +%b%d%Y-%H%M`".tar.gz"
  100.         fi
  101.         tar czvfp $DEST_TAR $SOURCE        # backup
  102.         md5sum $DEST_TAR > $DEST_NAME.md5        # make md5sum
  103.         ls -l $SOURCE_PATH > $DEST_NAME.list        # keep a list of this source
  104. }

  105. usage() {
  106.         echo "Usage: backup.sh [all | weekly | monthly]"
  107. }

  108. initiate
  109. prebackup

复制代码
发表于 2005-1-19 11:15:16 | 显示全部楼层
对于exec的使用还是不明白
楼主能否指点一二?
或者告诉我可以参考什么资料 ....

谢谢
回复 支持 反对

使用道具 举报

发表于 2005-1-19 11:57:10 | 显示全部楼层
man exec
然后输入/exec空格 回车
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-19 13:17:04 | 显示全部楼层
exec 7<&0和exec < $HOME/.backup这两句的意思是暂时将配置文件作为标准输入,这样我可以用read命令一行行读入文件的内容。读完之后必须把标准输出还给键盘,所以在prebackup函数最后又加了一行exec 7<&-
我是参考《Bash Guide for Beginners》第107页的例子,你可以看看
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-19 16:36:08 | 显示全部楼层
我发现没有必要用exec 7<&0和exec 7<&-,直接exec < $HOME/.backup就行了。
回复 支持 反对

使用道具 举报

发表于 2005-1-19 21:20:41 | 显示全部楼层
请问,香港的linux fans多不多?:p
回复 支持 反对

使用道具 举报

发表于 2005-1-19 22:04:53 | 显示全部楼层
支持! 备份方面的脚本精帖中也有一些, 可以参考一下,取长补短.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-20 00:40:58 | 显示全部楼层
Post by linux_now
请问,香港的linux fans多不多?:p

不太清楚,只知道有两个linux user group。我在的大学里也有为数不多的人在搞。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-23 22:04:12 | 显示全部楼层

系统备份脚本 [更新]

我按yongjian所说,搜索了一下以前的一些关于系统备份的帖子,发现分段备份是个好东西,于是收录进来。这次代码改动很大,增加了几个功能:1、放备份文件的目录可以直接在配置文件中指定;2、支持分段备份;3、用户可以选择是否对备份进行注释。
具体如下:
新增加了三个选项可以写在配置文件中,DEST,PART_TOGGLE还有LOG_TOGGLE。第一个DEST变量的内容是放备份文件的目录(注意,该变量并没有默认值,所以请用户一定要在配置文件中对该变量进行设定才能使用!!!);PART_TOGGLE则说明是否需要分段备份,0代表不分段(这也是默认值),任何大于0的值都将被看做是以Kilobytes为单位的每个分段的大小。最后那个LOG_TOGGLE变量表示是否在备份结束时对该次备份进行注释,有yes和no这两种值(默认为no),如果选yes的话将会在备份文件所在目录添加一个.log为扩展名的文件并打开vim来书写注释。除了DEST变量以外,其他两个可有可无。最后关键字SP:表示以下所有行都将当作需要备份的路径来处理。所以需要备份的路径一定要放到配置文件的最后来写。每个变量名后面跟一个冒号和空格之后就可以写相应的值。下面给出一个配置文件的例子:

  1. DEST: /mnt/usbc
  2. PART_TOGGLE: 10240
  3. LOG_TOGGLE: yes
  4. SP:
  5. weekly /home/neo
  6. weekly /etc
  7. weekly /var
  8. monthly / --exclude=/etc/* --exclude=/home/* --exclude=/var/* --exclude=/tmp/* --exclude=/proc/*
复制代码


这是更改后的脚本文件,请大家帮忙测试,确保在你机器上正常运行再使用!并多提意见和建议!谢谢


  1. #!/bin/bash

  2. # This script makes the backup of the system, the config file should be
  3. # in the home directory, called ".backuprc". The config file should
  4. # filled with options and several lines of the source pathes which you
  5. # want to be backed up. The options starts with the option name and then
  6. # followed by the values, for example, "DEST: /mnt/usbc" without quotes.
  7. # The name SP tells the script the following lines are source pathes.
  8. # Remember, source pathes always come at the end of the config file.
  9. # Each line has to in the format of this: "freq /source/path options".
  10. # the "freq" is the frequency you want this source to be backed up, and
  11. # "options" are the options you want to pass to tar. when running this
  12. # script you can specify the frequency you want to make backups this
  13. # time, for example: "backup.sh weekly". Then the script will pick the
  14. # matching source to backup. Currently there are three types of
  15. # frequency, which are "all", "weekly" and "monthly".
  16. # Written by Neo Anderson <ZeeGeek@gmail.com>
  17. # Jan 18 2005

  18. MTOGGLE=$1
  19. # set DEST to the destination which you want all the backup files go.
  20. # CAUTION, there's no default value for this variable, so you MUST
  21. # specify it in the config file.
  22. DEST=''
  23. # PART_TOGGLE specifies the size of each part of the target backup
  24. # file, 0 means don't cut, any number bigger than 0 will be treated as
  25. # Kilobytes of each part of the file.(default is 0)
  26. PART_TOGGLE=0
  27. # LOG_TOGGLE means whether or not you want to have a log when you
  28. # backup. (default is no)
  29. LOG_TOGGLE='no'

  30. initiate() {
  31.         # check if the user is running this script as root
  32.         if [ "$(whoami)" != 'root' ]
  33.         then
  34.                 echo "Please run this script as root!"
  35.                 exit
  36.         fi
  37.         # check if the destination directory exists
  38.         if [ ! -d $DEST ]
  39.         then
  40.                 echo "Destination directory not exists. Please create it before backup"
  41.                 exit
  42.         fi
  43.         cd /
  44. }

  45. readconf() {
  46.         # whether or not source path part has reached
  47.         SP='false'
  48.        
  49.         exec < $HOME/.backuprc        # redirect the input to the file .backup
  50.        
  51.         while read INPUT        # read the config file line by line
  52.         do
  53.                 if [ "`echo $INPUT | grep SP:`" ]
  54.                 then
  55.                         # read one more time to skip "SP:"
  56.                         if [ $SP == 'false' ]
  57.                         then
  58.                                 read INPUT
  59.                         fi
  60.                        
  61.                         # do checking
  62.                         initiate
  63.                         # toggle on
  64.                         SP='true'
  65.                         # get the frequency
  66.                         TOGGLE="`echo $INPUT | awk '{ print $1 }'`"
  67.                         # get the source path and options passed to tar
  68.                         SOURCE=${INPUT#$TOGGLE}
  69.                        
  70.                         # check the toggle provided by user when running this
  71.                         # script
  72.                         case $MTOGGLE in
  73.                                 weekly)
  74.                                         # if the toggle specified by user
  75.                                         # matches the toggle for each source,
  76.                                         # then back it up
  77.                                         if [ $MTOGGLE == $TOGGLE ]
  78.                                         then
  79.                                                 backup
  80.                                         else
  81.                                                 continue
  82.                                         fi
  83.                                         ;;
  84.                                 monthly)
  85.                                         if [ $MTOGGLE == $TOGGLE ]
  86.                                         then
  87.                                                 backup
  88.                                         else
  89.                                                 continue
  90.                                         fi
  91.                                         ;;
  92.                                 all)
  93.                                         backup
  94.                                         ;;
  95.                                 *)
  96.                                         usage
  97.                                         exit
  98.                                         ;;
  99.                         esac
  100.                 else
  101.                         TEMP="`echo $INPUT | awk '{ print $1 }' | sed s/.$//`"
  102.                         TEMP_V="`echo $INPUT | awk '{ print $2 }'`"
  103.                         case $TEMP in
  104.                                 DEST)
  105.                                         DEST=$TEMP_V
  106.                                         ;;
  107.                                 PART_TOGGLE)
  108.                                         PART_TOGGLE=$TEMP_V
  109.                                         ;;
  110.                                 LOG_TOGGLE)
  111.                                         LOG_TOGGLE=$TEMP_V
  112.                                         ;;
  113.                                 RM_OLD)
  114.                                         RM_OLD=$TEMP_V
  115.                                         ;;
  116.                                 *)
  117.                                         echo "unrecognized option $TEMP"
  118.                                         exit
  119.                                         ;;
  120.                         esac
  121.                 fi
  122.         done
  123. }

  124. backup() {
  125.         SOURCE_PATH="`echo $SOURCE | awk '{ print $1 }'`"
  126.         DEST_NAME="$DEST/`basename $SOURCE_PATH`"
  127.         DEST_TAR="$DEST_NAME."`date +%b%d%Y-%H%M`".tar.gz"
  128.         SIZE=$PART_TOGGLE

  129.         if [ $PART_TOGGLE == 0 ]
  130.         then
  131.                 tar czvfp $DEST_TAR $SOURCE        # backup
  132.                 md5sum $DEST_TAR > $DEST_NAME.md5        # make md5sum
  133.         else
  134.                 COUNTS=$[$PART_TOGGLE * 2]
  135.                 for ((a=1;;a++))
  136.                 do
  137.                         if [ "$SIZE" -ge "$PART_TOGGLE" ]
  138.                         then
  139.                                 TEMP_DEST_TAR="$DEST_TAR"."$a"
  140.                                 tar czvfp - $SOURCE | dd of=$DEST_TAR \
  141.                                 skip=$[$COUNTS * $[$a - 1]] count=$COUNTS
  142.                                 md5sum $DEST_TAR >> $DEST_NAME.md5
  143.                                 # size of last backuped part of file
  144.                                 SIZE="`ls -lk $DEST_TAR | awk '{ print $5}'`"
  145.                         else
  146.                                 break
  147.                         fi
  148.                 done
  149.         fi
  150.        
  151.         ls -lRa $SOURCE_PATH > $DEST_NAME.list        # keep a list of this source
  152.        
  153.         # make a log file
  154.         if [[ $LOG_TOGGLE == 'yes' || $LOG_TOGGLE == 'Yes' || \
  155.         $LOG_TOGGLE == 'YES' || $LOG_TOGGLE == 'Y' || \
  156.         $LOG_TOGGLE == 'y' ]]
  157.         then
  158.                 echo "# Log file for $DEST_NAME" > $DEST_NAME
  159.                 echo "# Written by `whoami`" >> $DEST_NAME
  160.                 echo "# `date +"%b %d %Y"`" >> $DEST_NAME
  161.                 vi $DEST_NAME.log
  162.         fi
  163. }

  164. usage() {
  165.         echo "Usage: backup.sh [all | weekly | monthly]"
  166. }

  167. # check the existance of the config file
  168. if [ ! -f $HOME/.backuprc ]
  169. then
  170.         echo "Config file not exist"
  171.         exit
  172. fi
  173. readconf
复制代码
回复 支持 反对

使用道具 举报

发表于 2005-1-24 11:26:03 | 显示全部楼层
兄弟我提些建议:
最好有一个--help选项,我查看了代码有usage函数,若有出错时能调用一下最好,像我执行了脚本后出现Config file not exist,但我不知道接下来如何做才能正常运行,再查看源码才发现要在root目录下有一个.backuprc文件,其中配置文件名称兄弟没有以何种方式告诉用户,这是对用户很不友好的
或者在初次运行时没有配置文件,能自动生成一个默认的配置文件,而不是用户去添加配置文件

我最后终于可以运行了,但不成功,信息如下:
dd: 无法识别的选项 ‘1月242005-1121.tar.gz’
请尝试执行‘dd --help’来获取更多信息。
tar: Removing leading `/' from member names
mnt/all/
mnt/all/play/
mnt/all/play/.cmd
mnt/all/play/.cmd/bzd
md5sum: /mnt/all/all.: 没有那个文件或目录
md5sum: 1月242005-1121.tar.gz: 没有那个文件或目录
ls: /mnt/all/all.: 没有那个文件或目录
ls: 1月242005-1121.tar.gz: 没有那个文件或目录
./backup: line 143: [: : integer expression expected
Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...

Vim: Finished.

上面是./backup all的输出。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表