LinuxSir.cn,穿越时空的Linuxsir!

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

从多个服务器上同时同步本地镜像

[复制链接]
发表于 2009-11-7 22:07:02 | 显示全部楼层 |阅读模式
苦于我这里的教育网里连不上 rsync (不知为何……),而外网速度又十分的慢,于是写了一个小脚本,可以同时从多个服务器上同步镜像,用人海战术来提高速度:
  1. #!/bin/zsh
  2. usage="mmirror-slack.sh mirror slackware tree from multiple servers.
  3. usage: mmirror-slack.sh [-vt]
  4.     v: be verbose. Display the commands that going to run.
  5.     f: final mode. Only synchronize with MAINMIRROR.
  6.     r: remove files that no present on remote server.
  7.     n: dry run. Display the commands going to run but not excute them.
  8.        Implies verbose.
  9. mmirror-slack.sh also receive parameters from environment variables:
  10.     VERSION: the version you want to mirror. -current, -13.0 etc.
  11.              Default is -current. Don't forget the leading '-'.
  12.     LOCALMIRROR: where is your mirror on the disk. Be sure to adjust
  13.              it before run this script.
  14.     ARCH: i386, x86_64 etc.
  15.     FOLDER: the folder under tree you want to mirror. slackware/, extra/ etc.
  16.              Don't forget the trailing '/'.
  17.     LEXTRAAGRS: extra arguments that passed to lftp.
  18.     AEXTRAAGRS: extra arguments that passed to aria2.
  19. "
  20. MAINMIRROR='ftp://ftp.osuosl.org/pub/slackware/'
  21. # add your favorite mirrors here
  22. MIRRORS=(ftp://darkstar.ist.utl.pt/pub/slackware/
  23. ftp://slackware.mirrors.tds.net/pub/slackware/
  24. http://mirrors.163.com/slackware/
  25. ftp://ftp.slackware.no/pub/linux/slackware/
  26. ftp://ftp.slackware.at/
  27. ftp://ftp.ntua.gr/pub/linux/slackware/
  28. http://mirror.switch.ch/ftp/mirror/slackware/
  29. ftp://ftp.heanet.ie/mirrors/ftp.slackware.com/pub/slackware/
  30. ftp://ftp.belnet.be/mirror/ftp.slackware.com/
  31. ftp://ftp.slackware.org.uk/slackware/
  32. http://slackware.cs.utah.edu/)
  33. MIRRORS+=$MAINMIRROR
  34. # -current or -13.0 etc. Don't forget the leading '-'.
  35. VERSION=${VERSION:-'-current'}
  36. # where your local mirror located. In that folder you should have some thing
  37. # like:
  38. #   slackware64-current/
  39. #   slackware-current/
  40. #   slackware-13.0/
  41. LOCALMIRROR=${LOCALMIRROR:-'/ext4/slackware_rsync'}
  42. # use ARCH to determine which branch to mirror.
  43. case $ARCH in
  44.         'x86_64' )
  45.         SBASE='slackware64'
  46.         TBASE=$SBASE
  47.         ;;
  48.         'i386' )
  49.         SBASE='slackware'
  50.         TBASE=$SBASE
  51.         ;;
  52.         * )
  53.         echo "ARCH=[x86_64|i386] mmirror-slack.sh"
  54.         echo "see source file for more parameters."
  55.         exit 1
  56.         ;;
  57. esac
  58. TDIR=${LOCALMIRROR}/${TBASE}${VERSION}/${FOLDER}
  59. SDIR=${SBASE}${VERSION}/${FOLDER}
  60. exec_lftp_cmd() {
  61.         cmd="lftp -c "$@""
  62.         [ $VERBOSE ] && echo $cmd
  63.         [ ! $DRYRUN ] && { eval $cmd || CMDFAIL+="\n""$cmd" }
  64. }
  65. fetch_cmd() {
  66.         # dump lftp commands to /proc/self/fd/3. Outer space must redirect 3 to
  67.         # stdout or what ever, or the programe will fail...
  68.         LEXTRAAGRS=${LEXTRAAGRS}' --verbose=3 --script=/proc/self/fd/3 '
  69.         # Some mirror have symbolic links, others are not. So for compatible
  70.         #   reason, use --dereference to download symbolic links as files.
  71.         #   Hope this won't get local mirror too large...
  72.         # If you behind good router and use good mirror, set ftp:sync-mode off
  73.         lftp -c "set ftp:sync-mode on
  74.                  open $MAINMIRROR &&
  75.                  mirror ${LEXTRAAGRS} \
  76.                    ${SDIR} ${TDIR}"
  77. }
  78. dispatch_cmd() {
  79.         while read -u 0 cmdline; do
  80.                 case ${cmdline[1,4]} in
  81.                         "get " )
  82.                         cmd=${cmdline//"$MAINMIRROR"/}
  83.                         file=$(echo "$cmd" | rev | cut -f 1 -d ' ' | rev)
  84.                         folder=$(echo "$cmd" | rev | cut -f 2 -d ' ' | rev)
  85.                         cmd="aria2c ${AEXTRAAGRS} --summary-interval=0 \
  86.                             --allow-overwrite=true --remote-time=true \
  87.                             --dir="${folder}" --split=${NMIRROR} \
  88.                             ${MIRRORS[@]/%/${file}}"
  89.                         [ $VERBOSE ] && echo $cmd
  90.                         [ ! $DRYRUN ] && { eval $cmd || DFAILFILE+="\n"${folder}$file }
  91.                         ;;
  92.                         * )
  93.                         exec_lftp_cmd $cmdline
  94.                         ;;
  95.                 esac
  96.         done
  97. }
  98. #############
  99. # Main body #
  100. #############
  101. NMIRROR=$((${#MIRRORS[@]}-1))
  102. while getopts ':vrfn' opt; do
  103.         case $opt in
  104.                 'v' )
  105.                 VERBOSE=1
  106.                 ;;
  107.                 'r' )
  108.                 REMOVEFILE=1
  109.                 LEXTRAAGRS+=" --delete "
  110.                 ;;
  111.                 'f' )
  112.                 MIRRORS=$MAINMIRROR
  113.                 NMIRROR=1
  114.                 ;;
  115.                 'n' )
  116.                 DRYRUN=1
  117.                 ;;
  118.                 '?' )
  119.                 unkopt+=$OPTARG' '
  120.                 ;;
  121.         esac
  122. done
  123. [ $DRYRUN ] && VERBOSE=1
  124. [ -n "$unkopt" ] && { echo "$usage"; echo "Unkown option: $unkopt"; exit 2}
  125. echo "Mirror $MAINMIRROR/$SDIR to $TDIR :"
  126. fetch_cmd 3>&1 1>&2 | dispatch_cmd
  127. [ -n "$DFAILFILE" ] && echo "\nfailed to download:" $DFAILFILE
  128. [ -n "$CMDFAIL" ] && echo "\nfailed to run command(s):" $CMDFAIL
  129. exit 0
复制代码

Update(2009年 11月 13日):
多谢 聚焦深空 的建议,现在脚本用 aria2 连接多服务器了。比自己重新发明轮子好多了(而且自己发明的轮子还没有别人跑得快……)

Update(Wed Nov 18 17:28:05 2009 +0800)
重写了很多东西,这回应该比较好用了~

Updated(2009年 12月 07日)
积累性更新。具体有什么不记得了……

代码放到 http://gitorious.org/slack-utils/slack-utils 上面了,欢迎提意见~;)
发表于 2009-11-7 23:27:27 | 显示全部楼层
不错,还真没这样想过
大多数的发行版一般都只允许设置一个MIRROR站点,多站点还真没试过
回复 支持 反对

使用道具 举报

发表于 2009-11-10 08:56:36 | 显示全部楼层
当时ArchLinux就有这类似的方法来提速的,但我好像没用过
对了, grissiom,这个是利用了lftp的续传+sync模式啊
还不知lftp有sync模式……
这个和rsync不一样吗?
这个是否会出现下载下来的包MD5值不一致的问题?如果会有,机率高吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-11-10 13:34:00 | 显示全部楼层
Post by slackcode;2044209
当时ArchLinux就有这类似的方法来提速的,但我好像没用过
对了, grissiom,这个是利用了lftp的续传+sync模式啊
还不知lftp有sync模式……
这个和rsync不一样吗?
这个是否会出现下载下来的包MD5值不一致的问题?如果会有,机率高吗?


用的是 lftp 的 mirror 模式,这个模式和 rsync 差不多但是:
1,rsync 一次把所有目录下需要传送的文件全部传过来,然后再传送具体的文件;而 lftp 是一个目录一个目录的扫描,这就慢很多……
2,rsync 是差量传送,lftp 是整个传送,理论上 rsync 要好~

不过我在的这个破网络 rsync 始终连不上去…… 用 lftp 是不得已而为之…… 不过 lftp 有个好处就是不用服务器端运行 rsync daemon。可用资源比较多~ 用的两次,出现过两次 md5sum 不合格的情况,不过那都是没有下载完的包……

我私下里正改进这个脚本,期望能够彻底解决重复下载的问题。不过被进程间通信这块快搞疯了,总是有 bug ……
回复 支持 反对

使用道具 举报

发表于 2009-11-10 18:31:23 | 显示全部楼层
您用支持从多个源、多线程同时下载的工具不是更省事么?如 aria2。
或使用支持 metalink 的工具下载,firefox 插件 downthemall 和 aria2 都支持,如果 slackware 支持此方式。
回复 支持 反对

使用道具 举报

发表于 2009-11-11 08:52:27 | 显示全部楼层
对,就是aria2,好像还有个叫axel的……
多镜像能解决单个服务器的流量限制吧,但有一个很明显的问题是,这些服务器的同步时间很可能不一致……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-11-11 09:17:47 | 显示全部楼层
Post by 聚焦深空;2044400
您用支持从多个源、多线程同时下载的工具不是更省事么?如 aria2。
或使用支持 metalink 的工具下载,firefox 插件 downthemall 和 aria2 都支持,如果 slackware 支持此方式。


多谢多谢~ 回头看看这个~;)
回复 支持 反对

使用道具 举报

发表于 2009-11-12 12:48:54 | 显示全部楼层
Post by slackcode;2044523
对,就是aria2,好像还有个叫axel的……
多镜像能解决单个服务器的流量限制吧,但有一个很明显的问题是,这些服务器的同步时间很可能不一致……

这个要靠自己小心,下载前应该检查各服务器上目标文件校验和。
metalink 方式,直接带有校验和,要安全的多。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-11-12 13:13:25 | 显示全部楼层
metalink 需要服务器端提供特殊服务么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-11-13 22:05:19 | 显示全部楼层
多谢 聚焦深空 的建议,现在脚本已经几乎重写了,用 aria2 下载而不是自己重新发明轮子~;)

如果哪位已经在用旧版本的严重建议升级~

感觉服务器上放出来的文件一般都是完整的,而且每做一次改动,包名都会不一样~这样的话如果有那个文件,一般就没错了~

metalink 貌似要一个文件一个 metalink 文件?和 zsync 有点像……
回复 支持 反对

使用道具 举报

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

本版积分规则

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