LinuxSir.cn,穿越时空的Linuxsir!

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

写脚本真得很头疼,外行呵!

[复制链接]
发表于 2008-5-29 23:42:15 | 显示全部楼层 |阅读模式
一个进行md5校验的下载arch的pkg文件作本地源的脚本(一)
zswlb999,发表于linuxsor.org上,2008-05-29
这是一个进行md5校验的下载arch的pkg文件作本地源的bash脚本。先将讲讲设计方法。最后将整个脚本贴出。第一次写脚本,写得不好,尤其是考虑错误处理方面,不太成熟。不管怎样,希望能对某些人有用。
web源码的一般形式为:
<img src="/icons/compressed.gif" alt="[   ]"> <a href="acl-2.2.47-1-i686.pkg.tar.gz">acl-2.2.47-1-i686.pkg.tar.gz</a>
将源码中的‘”’用‘\n'替换,,然后        就可以提取出pkg文件名了
wget http://mirrors.lcuc.org.cn/archlinux/core/os/i686/
得到一个index.html的文件,
sed -e 's/"/\n/' index.html|sed -e '/^.\+\.pkg\.tar\.gz$/!d'>$repo.file
第二个sed是将不是形式为×.pkg.tar.gz的行删掉,就得到$repo.file是一个全部是×.pkg.tar.gz文件了  
下载文件由downhtmldb实现,生成$repo.file文件由 dbfile2html实现
在downhtmldb下载的还有$repo.db.tar.gz
2)关于$repo.db.tar.gz
它是含有pkg文件的信息如CSIZE,MD5SUM,FILENAME,NAME,VERSION, 的全称,FILENAME是文件全名,也就是存档的名称,但并不是所有的文件都有这一项,否则就可以在这里取文件名就可以了。可能是旧的文件没有这一项。有些项我也不知道什么如 ISIZE.
将它解压后得到得是形如
NAME-VERSION/desc
NAME-VERSION是目录,desc是文件名,MD5SUM,CSIZE,NAME,VERSION的等就在这个文件里。
如acl-2.2.47-1-i686.pkg.tar.gz文件在.core.db.tar.gz里的NAME是acl,VERSION是2.2.47-1。在acl-2.2.47-1目录有一个desc的文件。
3)解压$repo.db.tar.gz
function extrdb()
{
read  -r -a name4db<<<$(tar -xvzf $1 -C  $ramfs/db$repo/  |sed -e '/\/$/!d;t end;/\/$/{s/\/$//; t end};:end' )
}
如果没有sed处理,得到的是含有
NAME-VERSION/desc,
NAME-VERSION/
的数组 name4db现在的name4db只包含形式为NAME-VERSION的数组,每一个NAME-VERSION对应一个pkg文件

4)取得本地的pkg文件, 在localfile实现。 $@ 是localfile的参数,即 pkg的目录所在(可以得到在不同的目录下的pkg文件)
ls -l $@ |awk '/^-/  {print $5"%"$NF>"slocale";print $NF>"locale";print "/"$NF"/d;t end">"locale4del"}'  &>/dev/null
locale就是一个本地pkg名单的文件,slocale是一个形如        size%name,locale4del(实际中加上$repo作为文件名)是一个形式为
/本地pkg文件/d;t end
.....
:end
的sed文件,它的作用是将服务器上的文件作比较,本地有的就除掉,得到的就是要下载的文件。



5)仅仅下载$repo.db.tar.gz有的文件。服务器上有一些文件是  $repo.db.tar.gz没有的,或者是旧的文件来保留,这些文件就不下载了,或者留在本地的旧文件不清除就可以了。
ls -l $ramfs/db$repo/ |awk '/^d/{print "s/^" $NF ".\\+pkg\\.tar\\.gz$/&/;t end"}END{print "/./d";print ":end"}'>$ramfs/dgcdb$repo
上式中$ramfs/db$repo是$repo.db.tar.gz解压到的目录,而生成的$ramfs/dgcdb$repo的内容就是
s/NAME-VERSION.\+pkg.tar.gz$/&/;t end         <----保留$repo.file 中$repo.db.tar.gz有的文件名
.........
/./d                                                               <----如果一个$repo.db.tar.gz中没有的文件,就在$repo.file 中删除
:end                                          
NAME-VERSION对应着repo.db.tar.gz中的每一个文件名。
,sed -f $ramfs/dgcdb$repo  $ramfs/$repo.file >${ramfs}/down${repo}       
down${repo}就是一个来自服务器上的web源码得到的而且在 $repo.db.tar.gz中存在的可供下载的文件表
6)由4)介绍得的locale4del$repo
read -r -a list4down<<<$(sed -f ${ramfs}/locale4del${repo}   ${ramfs}/down${repo})
list4down就是一个要下载的文件表了。

至于其他的部分,就不再介绍了,方法类似。都是sed和awk处理。用bash进行处理上述的文件处理更慢。
 楼主| 发表于 2008-5-29 23:46:29 | 显示全部楼层
一个进行md5校验的下载arch的pkg文件作本地源的脚本(源码一)
#!/bin/bash

#filename:getpkg.sh
#所需要的都写在一个文件里了。因为不是作为一个专业的东西,难为求得太精。
#如果同时运行即可能stop参数等功能可能会不能实现,是可能退出时删除了标志。

:<<BLOCK
注释
功能:使用arria2c从各地的archlinux的服务器源的下载文件到本地,用于做本地的源。
命令:
getpkg 参数1 参数2
参数1为:-auto  -md5  -stop
-auto:自动模式下载
-autof   :强制方式下载,没有实现
-md5 :对本地的文件进行md5校验。数据库采用本地的$repo.db.tar.gz
-stop:通知正在运行的脚本在正在下载的文件结束后停止下载,退出。它通过检测一个以文件通知的形式实现
-stop数字:通知正在运行的脚本在正在下载的文件结束后,检测时间如否超过规定的时间即退出。取前三位数字,单位分钟,
-off
-off 数字   同stop参数,但实现关机
功能。必须确保用户有关机的权限。以sudo poweroff 实现。
-show   显示正在运行的脚本的情况:
参数1只能选择一个,不能混用
参数2为:-comm (等效于-community) -core -extra -m -m[0-3] )
参数可选择多个
以下的参数没有实现
-m:下载方式选择
-m为默认 使用aria2c
-m1使用wget
-m2以aria2c为主,下载大文件,wget下载小文件为辅   未实现(两者使用不同的url,并且依据通信状况动态改变url)
-m3以wget为主,下载大文件,aria2c下载小文件为辅   未实现(两者使用不同的url,)
------------------------------------------
一般的使用方法为:
getpkg -auto -community -core    或getpkg -auto
getpkg  -md5 -community -core    或getpkg -md5
getpkg  -stopXX      xx 是数字
getpkg -debug
等等

BLOCK
#81091650
#
declare -f  updata  dbinfo downfile   delfile

##################################################333
#增加repo时,修改SECTION readstatu()
#变更repo 目录时,修改DEST
#####################################################3

RSYNC_HOST=rsync://mirrors.easynews.com
RSYNC_ROOT=mirrors/linux/archlinux
DOWN_HOST=http://mirrors.lcuc.org.cn/archlinux
DOWN_ROOT=archlinux
#RSYNC_PROXY="10.1.32.232:808"
#HTTP_PROXY="http://10.1.32.232:808"
SECTION=( "core" "extra" "community")   
#要增加源项,还要修改命令行参数部分,除非不带此类参数,如archrepofile -auto;   archrepofile   -md5
section=()

#---------------------------------------------------
MAX_ERRORS=3
ERROR_NUM=0
ERROR_NUM0=0



#---------------------------目录-----------------------
DEST="/data/archlinux"       #源文件存放目录为$DEST/$repo/os/${ARCH}
STATU="${DEST}/statu"        
DOWN="${DEST}"
TMP=${DEST}/tmp          #工作目录
RAMFS=$TMP/ramfs         #ramfs文件系统挂载点
#--------------------------------------
LOG=${DEST}/sync_log  #日志文件
ARCH=i686

#------------------------------------------------------

#-------------------------目录及文件结构----------------------------------------
#${DEST}:目录起点,要求有读写的权限
#$DEST/$repo/os/${ARCH} 存放·pkg.tar.gz文件
#${DEST}/statu:存在状态信息,下载的文件清单文件,如core.db.tar.gz数据文件,本脚本的log文件statu.run文件均存放在此
#${DEST}/tmp${repo}:存放下载时的pkg.tar.gz文件  、及其aria2c 的日志目录,下载文件的临时目录
#${TMP}/ramfs/db${repo}:  core.db.tar.gz数据文件解压后的文件


#--------------------------------------------------------------------

#rm -f


:<<BLOCK
注释==辅助函数说明
init()初始化环境主要是:
check_dir()
检查$DEST目录是否具有读写权限
建立工作目录 $TMP下的各级子目录
mountramfs() 挂载ramfs文件系统,
------------------------------------------
命令参数处理
arghandl()
BLOCK
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-29 23:47:19 | 显示全部楼层
一个进行md5校验的下载arch的pkg文件作本地源的脚本(续前:源码二)

function EXIT()
{
#这里本来可以根据退出码来作详细的动作
if [[ ${STOP} != 1 ]];
then
rm -f $STATU/ramfs.txt  $ramfs/stop.run  $ramfs/poweroff.txt  &>/dev/null

exit $1

fi
exit $1
}

function mountramfs()
{
local MOUNT path ramfs


path=$(mount |awk '($5 ~ /ramfs/) && ($3 !~ /\/dev/) {print $3}')
echo  $path
MOUNT=F
for path0 in ${path[@]}
do
if  [[  -r  $path0  ]]  &&  [[   -w   $path0 ]] ;then

echo "发现一个可读写的ramfs文件系统挂载在$path0"
ramfs=$path0
MOUNT=T
break
else
MOUNT=F
fi
done
if [[ "$MOUNT" = "F" ]]
   then
   [[ -z $1 ]] && echo "$FUNCNAME::参数空,不挂载ramfs系统" && return 1
   ramfs=$RAMFS
   echo "sudo mount -t ramfs none $TMP/ramfs -o maxsize=4096 "
   sudo mount -t ramfs none $TMP/ramfs -o maxsize=4096    #  - 以k为单位  
     if [ ! -r $ramfs ] || [ ! -w $ramfs ] ;
     then
     echo "目录不可读写$ramfs "
     sudo chmod -R 777  $ramfs/  
     if [ $?  = 0 ] ;then
     echo "更改目录权限失败$ramfs"
     EXIT   
     fi
     fi
fi
eval $1=$ramfs
unset MOUNT path ramfs
}

#挂载ramfs文件系统
function check_dir()
{
[[ "${#section[@]}" -ge 1 ]] && SECTION=( ${section[@]} )

if   [ -e  "${DEST}" ] && [ -w  "${DEST}" ];  then
mkdir -p   ${STATU}   $RAMFS
     if [ ! -w  ${TMP} ];then
     echo "函数$FUNCNAME{TMP}目录不存在或没有写权限。退出"   &&  return  1
     fi
fi
rm -rf $RAMFS/*
mountramfs ramfs
for repo in ${SECTION[@]}
do
mkdir -p $DOWN/$repo/os/$ARCH $ramfs/db$repo $TMP/tmp$repo  2>/dev/null

done
return 0
}

function init()
{
ramfs=$RAMFS
echo "::来自::函数$FUNCNAME::初始化目录"
check_dir
if [ $? != 0 ] ;then      
echo "来自::函数$FUNCNAME::行号:LINENO::目录权限错误,退出运行 " && EXIT 1
fi
echo 函数$FUNCNAMErcore
cd  ${TMP} #进入工作目录
echo "$ramfs">$STATU/ramfs.txt   2>/dev/null
echo "来自::函数$FUNCNAME::行号:LINENO::初始化目录结束"
rm $LOG  &>/dev/null
return $?  #读装态成功否                 ???这里的$?好像是多余的,它返回的只是rm的退出码,没有多大的实际意义。check_dir 的退出码在前面已处理  20008-05-53-31
}

function program_init()
{
:
echo "$FUNCNAME"
echo repo is

echo SECTION

echo ${SECTION[@]}
echo  action
echo ${action[@]}

}

#echo $ramfs
#对命令行参数分类
function arghandl()
{
local arg
arg=
action=()
echo $@

until [ -z "$1" ]  # 直到所有的位置参数都被存取完...
do
case $1 in
-md5)
action=( "${action[@]}" md5 )
;;
-init)
action=( ${action[@]} init )
;;
-auto)
action=( ${action[@]} auto )
;;
-autof)
action=( ${action[@]} autof )
;;
-f)
action=( ${action[@]} force )
;;
-stop)

action=( ${action[@]} stop )
;;
-stop[0-9]*)
arg=$1
arg=${arg:5:7}
action=( ${action[@]} $arg )
;;
-off)
action=( ${action[@]} off )
;;
-off[0-9]*)
arg=$1
arg=${arg:4:7}
action=( ${action[@]} $arg )
;;
-debug)
action=( ${action[@]} debug )
;;

-h)

echo "命令使用格式"
EXIT
#action=( ${action[@]} -help)


;;
-core)
section=(${section[@]}  core )
;;
-community)
section=(${section[@]}  community )
;;
-comm)
section=(${section[@]}  community )
;;
-extra)
section=(${section[@]}  extra )
;;
*)
echo "非法参数${i}"
EXIT
;;
esac
shift
done
unset arg
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-29 23:59:45 | 显示全部楼层
function program_o()
{
echo "getpkg -auto -community -core    或getpkg -auto"
echo "getpkg  -md5 -community -core    或getpkg -md5"
echo "getpkg  -stopxxx      xx 是数字"
exit
}


#根据命令行参数调用相应的函数
function main()
{
STOP=0
[[ -s  $STATU/ramfs.txt ]] && read ramfs <$STATU/ramfs.txt  || ramfs=$RAMFS  #这是为使用stop等参数
#PROGRAM=( program_o    program_md5  program_auto  program_init  other )
       #初始化,检测是否第一次运行
#进入执行命令
case  "${#action[@]}" in
0)
        program_o  
   #   act=program_o         #命令行没有主要参数参数
;;                 #1个主参数
1)                 #多于一个,非法
      case ${action[0]} in    #执行参数对应的程序
      md5)
        act="program_md5"
       ;;
      auto)

        act="program_auto"
      ;;
      autof)

        act="program_autof"
      ;;
      init)
            act=program_init         #强制初始化后再执行,从新开始
      ;;
      stop)             #有关停机部分在下载downfile中处理      
            STOP=1
        echo "s"> $ramfs/stop.run
        echo  "已发送发送终止下载消息"
        EXIT
        ;;
       stop[0-9]*)
        STOP=1

        echo "p">$ramfs/stop.run
        time0=`date +%s`
        mtime=${action[$i]:3:3}
        ((time0=time0+mtime*60))
        echo  “p$time0” >$ramfs/stop.run
        echo  "已发送发送消息:$mtime分钟后终止下载"
        EXIT
        
       ;;
        off)
            STOP=1
        echo  “p” >$ramfs/stop.run
        echo  "已发送发送关机消息"
        EXIT
        ;;
        off[0-9]*)       
        STOP=1
        time0=`date +%s`
        mtime=${action[$i]:3:3}
        ((time0=time0+mtime*60))
        echo  “p$time0” >$ramfs/stop.run
        echo  "已发送发送消息:$mtime分钟后关机"
        EXIT
        #
       ;;
       poweroff)
         STOP=1
       echo "s"> $ramfs/poweroff.run
        ;;       

      debug)
        act=debug
      ;;
      *)
      echo "没有注册的命令参数${action[0]} "
      EXIT
        ;;
      esac
;;
*)
echo "这些参数不能同时使用 ${action[@]}"  && EXIT 1
;;
esac
ramfs=
init

}


function init_url()  #初始化服务器url
{
local repo
repo='$'repo
read -r -a url<<<$(cat<<EOF
ftp://cle.linux.org.tw/pub/ArchLinux/$repo/os/$ARCH
ftp://ftp.nethat.com/pub/linux/archlinux/$repo/os/$ARCH
http://mirror.pacific.net.au/linux/archlinux/$repo/os/$ARCH
http://mirror.lupaworld.com/archlinux/$repo/os/$ARCH
http://darkstar.ist.utl.pt/archlinux/$repo/os/$ARCH
http://mirror.isoc.org.il/pub/archlinux/$repo/os/$ARCH
http://www.mirrorservice.org/sites/ftp.archlinux.org/$repo/os/$ARCH
http://archlinux.mirrors.uk2.net/$repo/os/$ARCH
http://mirrors.easynews.com/linux/archlinux/$repo/os/$ARCH
http://mirror.isoc.org.il/pub/archlinux/$repo/os/$ARCH
EOF
)
unset repo
}
#http://mirrors.lcuc.org.cn/archlinux/$repo/os/$ARCH
# 设置建立文件目录



#从给定的服务器下载更新文件
function stopeven()
{
local stop time0 time1
stop=0
time0=0
time1=0

    if [ -s $ramfs/stop.run ] ;then
    read stop< $ramfs/stop.run
            case ${stop:=0} in
        [0s])
             echo "发现停机信号,终止,退出运行"
             echo "发现停机信号,终止,退出运行:repo::stop at::" `date`>>$LOG
        EXIT 2
        ;;
        p)
        echo "发现关机信号,关机:repo::stop at::" `date`
        echo "发现关机信号,关机:repo::stop at::" `date`>>$LOG
        sudo poweroff
        EXIT
        ;;
        s[0-9]*)
        time0=${stop:1:3}
        time1=`date +%s`
        if [[ $((time1-time0)) -gt 0 ]] ;then
        echo "发现停机信号,退出运行"
             echo "发现停机信号,退出运行:repo::stop at::" `date`>>$LOG
        EXIT
        fi
        ;;
        [p])
        echo "发现关机信号,关机:repo::stop at::" `date`
        echo "发现关机信号,关机:repo::stop at::" `date`>>$LOG
        sudo poweroff   
        EXIT  #如果不能关机
        ;;
        p[0-9]*)
        time0=${stop:1:3}
        time1=`date +%s`
        if [[ $((time1-time0)) -gt 0 ]] ;then
            echo "发现停机信号,终止, 关机:repo::stop at::" `date`>>$LOG
             sudo poweroff
           echo  "关机失败:repo::stop at::" `date`>>$LOG
            fi
        ;;
            esac
    fi
unset time0 time1 stop
}
function downfile()
{

local err err1  stop  j len
init_url
err=0
err1=0
j=0
len=0
eval echo ${url[@]} 1>/dev/null

until [ ${#list4down[@]} = 0 ]
do

len=${#list4down[@]}
for ((j=0;j<${#list4down[@]};j++))
do
pkg=${list4down[$j]}
pkg=${pkg##*%}

stopeven
if [[ -f $TMP/tmp$repo/$pkg ]];then
   echo "文件已存在:TMP/tmp$repo/$pkg::略过"
   list4down[$j]=
   continue
fi
for ((i=0;i<${#url[@]};i++))
do
eval '  mirrors[$i]='${url[$i]}'/${pkg}'
done
   echo ${mirrors[@]} >/dev/null
   echo "下载${repo}文件{len}/${j}:${mirrors[0]}"
#???   rm -f ${TMP}/tmp${repo}/${pkg}.pacget.aria2  ${TMP}/tmp${repo}/${pkg}.pacget

  # aria2c -s1 -t35 -m1  -c  -j8 -l ${TMP}/${repo}.pacget.log ${mirrors[@]}  -d ${TMP}/tmp${repo} -o ${pkg}.pacget
aria2c  -t35 -m1  -c   -l ${TMP}/${repo}.pacget.log ${mirrors[@]}  -d ${TMP}/tmp${repo} -o ${pkg}.pacget

   if  [[ -f ${TMP}/tmp${repo}/${pkg}.pacget.aria2 ]] ;then
   rm -f ${TMP}/tmp${repo}/${pkg}.pacget   ${TMP}/tmp${repo}/${pkg}.pacget.aria2
   fi
     if [[ $? = 0 ]] && [[ -s ${TMP}/tmp${repo}/${pkg}.pacget ]];then
     mv ${TMP}/tmp${repo}/${pkg}.pacget  ${TMP}/tmp${repo}/${pkg}
     list4down[$j]=  
     err=0
     else
     [ $((++err)) = 3  ] && echo "连续下载错误。终止" && mesg="9-%$FUNCNAME%" && list4down=(${list4down[@]}) && return 9
     fi   #mesg="9-%$FUNCNAME%"暂时没有使用
done

list4down=(${list4down[@]})
[[ $((++err1)) = 2 ]] && unset  err  err1   && return 9
done
unset err  err1  stop  j

}

function do_rsync()
{
#备用下载方式eval STEP=3  

#rsync -avz --no-l --no-H --no-p --no-o --no-g --delete-after  \
#${RSYNC_HOST}/${RSYNC_ROOT}/${repo}/os/${ARCH}/   $DOWN/$repo/os/$ARCH/
rsync -avz --no-l --no-H --no-p --no-o --no-g --delete-after --size-only \
${RSYNC_HOST}/${RSYNC_ROOT}/${repo}/os/${ARCH}/   $DOWN/$repo/os/$ARCH/
}

#EXIT
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-30 00:01:25 | 显示全部楼层
#一个进行md5校验的下载arch的pkg文件作本地源的脚本(源码二)



function EXIT()
{
#这里本来可以根据退出码来作详细的动作
if [[ ${STOP} != 1 ]];
then
rm -f $STATU/ramfs.txt  $ramfs/stop.run  $ramfs/poweroff.txt  &>/dev/null

exit $1

fi
exit $1
}

function mountramfs()
{
local MOUNT path ramfs


path=$(mount |awk '($5 ~ /ramfs/) && ($3 !~ /\/dev/) {print $3}')
echo  $path
MOUNT=F
for path0 in ${path[@]}
do
if  [[  -r  $path0  ]]  &&  [[   -w   $path0 ]] ;then

echo "发现一个可读写的ramfs文件系统挂载在$path0"
ramfs=$path0
MOUNT=T
break
else
MOUNT=F
fi
done
if [[ "$MOUNT" = "F" ]]
   then
   [[ -z $1 ]] && echo "$FUNCNAME::参数空,不挂载ramfs系统" && return 1
   ramfs=$RAMFS
   echo "sudo mount -t ramfs none $TMP/ramfs -o maxsize=4096 "
   sudo mount -t ramfs none $TMP/ramfs -o maxsize=4096    #  - 以k为单位  
     if [ ! -r $ramfs ] || [ ! -w $ramfs ] ;
     then
     echo "目录不可读写$ramfs "
     sudo chmod -R 777  $ramfs/  
     if [ $?  = 0 ] ;then
     echo "更改目录权限失败$ramfs"
     EXIT   
     fi
     fi
fi
eval $1=$ramfs
unset MOUNT path ramfs
}

#挂载ramfs文件系统
function check_dir()
{
[[ "${#section[@]}" -ge 1 ]] && SECTION=( ${section[@]} )

if   [ -e  "${DEST}" ] && [ -w  "${DEST}" ];  then
mkdir -p   ${STATU}   $RAMFS
     if [ ! -w  ${TMP} ];then
     echo "函数$FUNCNAME{TMP}目录不存在或没有写权限。退出"   &&  return  1
     fi
fi
rm -rf $RAMFS/*
mountramfs ramfs
for repo in ${SECTION[@]}
do
mkdir -p $DOWN/$repo/os/$ARCH $ramfs/db$repo $TMP/tmp$repo  2>/dev/null

done
return 0
}

function init()
{
ramfs=$RAMFS
echo "::来自::函数$FUNCNAME::初始化目录"
check_dir
if [ $? != 0 ] ;then      
echo "来自::函数$FUNCNAME::行号:LINENO::目录权限错误,退出运行 " && EXIT 1
fi
echo 函数$FUNCNAMErcore
cd  ${TMP} #进入工作目录
echo "$ramfs">$STATU/ramfs.txt   2>/dev/null
echo "来自::函数$FUNCNAME::行号:LINENO::初始化目录结束"
rm $LOG  &>/dev/null
return $?  #读装态成功否
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-30 00:02:32 | 显示全部楼层
##一个进行md5校验的下载arch的pkg文件作本地源的脚本(源码三)
function program_init()
{
:
echo "$FUNCNAME"
echo repo is

echo SECTION

echo ${SECTION[@]}
echo  action
echo ${action[@]}

}

#echo $ramfs
#对命令行参数分类
function arghandl()
{
local arg
arg=
action=()
echo $@

until [ -z "$1" ]  # 直到所有的位置参数都被存取完...
do
case $1 in
-md5)
action=( "${action[@]}" md5 )
;;
-init)
action=( ${action[@]} init )
;;
-auto)
action=( ${action[@]} auto )
;;
-autof)
action=( ${action[@]} autof )
;;
-f)
action=( ${action[@]} force )
;;
-stop)

action=( ${action[@]} stop )
;;
-stop[0-9]*)
arg=$1
arg=${arg:5:7}
action=( ${action[@]} $arg )
;;
-off)
action=( ${action[@]} off )
;;
-off[0-9]*)
arg=$1
arg=${arg:4:7}
action=( ${action[@]} $arg )
;;
-debug)
action=( ${action[@]} debug )
;;

-h)

echo "命令使用格式"
EXIT
#action=( ${action[@]} -help)


;;
-core)
section=(${section[@]}  core )
;;
-community)
section=(${section[@]}  community )
;;
-comm)
section=(${section[@]}  community )
;;
-extra)
section=(${section[@]}  extra )
;;
*)
echo "非法参数${i}"
EXIT
;;
esac
shift
done
unset arg
}
function program_o()
{
echo "getpkg -auto -community -core    或getpkg -auto"
echo "getpkg  -md5 -community -core    或getpkg -md5"
echo "getpkg  -stopxxx      xx 是数字"
exit
}


#根据命令行参数调用相应的函数
function main()
{
STOP=0
[[ -s  $STATU/ramfs.txt ]] && read ramfs <$STATU/ramfs.txt  || ramfs=$RAMFS  #这是为使用stop等参数
#PROGRAM=( program_o    program_md5  program_auto  program_init  other )
       #初始化,检测是否第一次运行
#进入执行命令
case  "${#action[@]}" in
0)
        program_o  
   #   act=program_o         #命令行没有主要参数参数
;;                 #1个主参数
1)                 #多于一个,非法
      case ${action[0]} in    #执行参数对应的程序
      md5)
        act="program_md5"
       ;;
      auto)

        act="program_auto"
      ;;
      autof)

        act="program_autof"
      ;;
      init)
            act=program_init         #强制初始化后再执行,从新开始
      ;;
      stop)             #有关停机部分在下载downfile中处理      
            STOP=1
        echo "s"> $ramfs/stop.run
        echo  "已发送发送终止下载消息"
        EXIT
        ;;
       stop[0-9]*)
        STOP=1

        echo "p">$ramfs/stop.run
        time0=`date +%s`
        mtime=${action[$i]:3:3}
        ((time0=time0+mtime*60))
        echo  “p$time0” >$ramfs/stop.run
        echo  "已发送发送消息:$mtime分钟后终止下载"
        EXIT
        
       ;;
        off)
            STOP=1
        echo  “p” >$ramfs/stop.run
        echo  "已发送发送关机消息"
        EXIT
        ;;
        off[0-9]*)       
        STOP=1
        time0=`date +%s`
        mtime=${action[$i]:3:3}
        ((time0=time0+mtime*60))
        echo  “p$time0” >$ramfs/stop.run
        echo  "已发送发送消息:$mtime分钟后关机"
        EXIT
        #
       ;;
       poweroff)
         STOP=1
       echo "s"> $ramfs/poweroff.run
        ;;       

      debug)
        act=debug
      ;;
      *)
      echo "没有注册的命令参数${action[0]} "
      EXIT
        ;;
      esac
;;
*)
echo "这些参数不能同时使用 ${action[@]}"  && EXIT 1
;;
esac
ramfs=
init

}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-30 00:03:47 | 显示全部楼层
function init_url()  #初始化服务器url
{
local repo
repo='$'repo
read -r -a url<<<$(cat<<EOF
ftp://cle.linux.org.tw/pub/ArchLinux/$repo/os/$ARCH
ftp://ftp.nethat.com/pub/linux/archlinux/$repo/os/$ARCH
http://mirror.pacific.net.au/linux/archlinux/$repo/os/$ARCH
http://mirror.lupaworld.com/archlinux/$repo/os/$ARCH
http://darkstar.ist.utl.pt/archlinux/$repo/os/$ARCH
http://mirror.isoc.org.il/pub/archlinux/$repo/os/$ARCH
http://www.mirrorservice.org/sites/ftp.archlinux.org/$repo/os/$ARCH
http://archlinux.mirrors.uk2.net/$repo/os/$ARCH
http://mirrors.easynews.com/linux/archlinux/$repo/os/$ARCH
http://mirror.isoc.org.il/pub/archlinux/$repo/os/$ARCH
EOF
)
unset repo
}
#http://mirrors.lcuc.org.cn/archlinux/$repo/os/$ARCH
# 设置建立文件目录



#从给定的服务器下载更新文件
function stopeven()
{
local stop time0 time1
stop=0
time0=0
time1=0

    if [ -s $ramfs/stop.run ] ;then
    read stop< $ramfs/stop.run
            case ${stop:=0} in
        [0s])
             echo "发现停机信号,终止,退出运行"
             echo "发现停机信号,终止,退出运行:repo::stop at::" `date`>>$LOG
        EXIT 2
        ;;
        p)
        echo "发现关机信号,关机:repo::stop at::" `date`
        echo "发现关机信号,关机:repo::stop at::" `date`>>$LOG
        sudo poweroff
        EXIT
        ;;
        s[0-9]*)
        time0=${stop:1:3}
        time1=`date +%s`
        if [[ $((time1-time0)) -gt 0 ]] ;then
        echo "发现停机信号,退出运行"
             echo "发现停机信号,退出运行:repo::stop at::" `date`>>$LOG
        EXIT
        fi
        ;;
        [p])
        echo "发现关机信号,关机:repo::stop at::" `date`
        echo "发现关机信号,关机:repo::stop at::" `date`>>$LOG
        sudo poweroff   
        EXIT  #如果不能关机
        ;;
        p[0-9]*)
        time0=${stop:1:3}
        time1=`date +%s`
        if [[ $((time1-time0)) -gt 0 ]] ;then
            echo "发现停机信号,终止, 关机:repo::stop at::" `date`>>$LOG
             sudo poweroff
           echo  "关机失败:repo::stop at::" `date`>>$LOG
            fi
        ;;
            esac
    fi
unset time0 time1 stop
}
function downfile()
{

local err err1  stop  j len
init_url
err=0
err1=0
j=0
len=0
eval echo ${url[@]} 1>/dev/null

until [ ${#list4down[@]} = 0 ]
do

len=${#list4down[@]}
for ((j=0;j<${#list4down[@]};j++))
do
pkg=${list4down[$j]}
pkg=${pkg##*%}

stopeven
if [[ -f $TMP/tmp$repo/$pkg ]];then
   echo "文件已存在:TMP/tmp$repo/$pkg::略过"
   list4down[$j]=
   continue
fi
for ((i=0;i<${#url[@]};i++))
do
eval '  mirrors[$i]='${url[$i]}'/${pkg}'
done
   echo ${mirrors[@]} >/dev/null
   echo "下载${repo}文件{len}/${j}:${mirrors[0]}"
#???   rm -f ${TMP}/tmp${repo}/${pkg}.pacget.aria2  ${TMP}/tmp${repo}/${pkg}.pacget

  # aria2c -s1 -t35 -m1  -c  -j8 -l ${TMP}/${repo}.pacget.log ${mirrors[@]}  -d ${TMP}/tmp${repo} -o ${pkg}.pacget
aria2c  -t35 -m1  -c   -l ${TMP}/${repo}.pacget.log ${mirrors[@]}  -d ${TMP}/tmp${repo} -o ${pkg}.pacget

   if  [[ -f ${TMP}/tmp${repo}/${pkg}.pacget.aria2 ]] ;then
   rm -f ${TMP}/tmp${repo}/${pkg}.pacget   ${TMP}/tmp${repo}/${pkg}.pacget.aria2
   fi
     if [[ $? = 0 ]] && [[ -s ${TMP}/tmp${repo}/${pkg}.pacget ]];then
     mv ${TMP}/tmp${repo}/${pkg}.pacget  ${TMP}/tmp${repo}/${pkg}
     list4down[$j]=  
     err=0
     else
     [ $((++err)) = 3  ] && echo "连续下载错误。终止" && mesg="9-%$FUNCNAME%" && list4down=(${list4down[@]}) && return 9
     fi   #mesg="9-%$FUNCNAME%"暂时没有使用
done

list4down=(${list4down[@]})
[[ $((++err1)) = 2 ]] && unset  err  err1   && return 9
done
unset err  err1  stop  j

}

function do_rsync()
{
#备用下载方式eval STEP=3  

#rsync -avz --no-l --no-H --no-p --no-o --no-g --delete-after  \
#${RSYNC_HOST}/${RSYNC_ROOT}/${repo}/os/${ARCH}/   $DOWN/$repo/os/$ARCH/
rsync -avz --no-l --no-H --no-p --no-o --no-g --delete-after --size-only \
${RSYNC_HOST}/${RSYNC_ROOT}/${repo}/os/${ARCH}/   $DOWN/$repo/os/$ARCH/
}

#EXIT

function getdbinfo()
{
#第一个参数解压数据库后得到的文件名列表数组名
local getname
if [ -z "$1" ] ;then
echo "函数$FUNCNAME:参数不能空,返回"
return 1
fi
rm -f  $ramfs/sizenamedb$repo.sed $ramfs/md5namedb$repo.sed $ramfs/md5namedb$repo.sed
   #取数组名
  #传名参数,数组
eval 'len=${#'$1'[@]}'
# echo '/\.pkg\.tar\.gz$/!d;t end'>$ramfs/sizenamedb$repo.sed   #因为生成本地地文件时采用ls -l *.pkg.tar.gz已限制了其他文件,可以减少几千次比较
# echo '/\.pkg\.tar\.gz$/!d;t end'>$ramfs/md5namedb$repo.sed
echo 's/\s\+/%/'>>$ramfs/md5namedb$repo.sed
#echo '/\.pkg\.tar\.gz$/!d;t end'>$ramfs/md5name4del$repo.sed
echo 's/\s\+/%/'>$ramfs/md5name4del$repo.sed
for ((j=0;j<$len;j++))
do
eval 'getname=${'$1'['$j']}'
getname=${getname%%.pkg.tar.gz}
getname=${getname%%-$ARCH}
getname=${getname##*/}

if [ -e ${ramfs}/db$repo/${getname}/desc ];
then

  # echo \$i=$i:$getname
   while read line
   do
   case $line in
     %CSIZE%)
     read size[$j]
   ;;
   %MD5SUM%)
    read  md5[$j]
;;
   %NAME%)
   read name[$j]
   ;;
        %VERSION%)
        read ver[$j]       
        ;;
   esac
   done  <${ramfs}/db$repo/${getname}/desc
   echo 's/^'${size[$j]}'%'${name[$j]}'-'${ver[$j]}'/'${name[$j]}'-'${ver[$j]}'/;t end'>>$ramfs/sizenamedb$repo.sed                #size+name+ver
   echo 's/^'${md5[$j]}'%'${name[$j]}'-'${ver[$j]}'/'${name[$j]}'-'${ver[$j]}'/;t end'>>$ramfs/md5namedb$repo.sed      
             #md5+name+ver
              #size+name+ver  
   echo '/^'${md5[$j]}'%'${name[$j]}'-'${ver[$j]}'/d;t end'>>$ramfs/md5name4del$repo.sed      
else
echo "函数$FUNCNAME:文件${ramfs}/db$repo/${getname}/desc不存在,请检查。返回"
fi
done
   echo '/./d'>>$ramfs/sizenamedb$repo.sed
   echo ':end'>>$ramfs/sizenamedb$repo.sed               #size+name+ver
#   echo 's/^.\+%//'>>$ramfs/sizenamedb
   echo '/./d'>>$ramfs/md5namedb$repo.sed
   echo ':end'>>$ramfs/md5namedb$repo.sed
  # echo "/^.\+\.db\.tar\.gz$/d">>$ramfs/md5name4del$repo.sed  
   echo 's/^.\+%//'>>$ramfs/md5name4del$repo.sed  
   echo ':end'>>$ramfs/md5name4del$repo.sed                 #md5+name+ver
#   echo ';s/^.\+%//'>>$ramfs/md5namedb
#生成一个sed文件,功能:将已下载的文件名及大小相同的文件表
#eval 'filename'$repo'['$i']'='${FILENAME%/*}'
#checkmd5  $path0/repo/tmp.$repo
} #end of read readinfo
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-30 00:04:44 | 显示全部楼层
#下载$repo.db.tar.gz
function getdb()
{
local LOCAL_SECTION I repo err
LOCAL_SECTION=( ${SECTION[@]} )
err=0
until [ "${#LOCAL_SECTION[@]}" = 0 ]
do
for ((I=0;I<${#LOCAL_SECTION[@]};I++))
do
repo=${LOCAL_SECTION[$I]}
rsync -cv  $RSYNC_HOST/$RSYNC_ROOT/$repo/os/${ARCH}/$repo.db.tar.gz .
if [ -f $repo.db.tar.gz ] ;then
LOCAL_SECTION[$I]=
fi
done
LOCAL_SECTION=( ${LOCAL_SECTION[@]} )
[ $((++err)) = 2 ] && return 1

done
mv -f *.db.tar.gz $STATU/
unset I LOCAL_SECTION repo err

}
function localfile()
{
#取得的本地文件目录  一般为$DEST/$REPO/OS/${ARCH}/ 及  $DEST/TMP$REPO/
[[ $# =  0 ]] && echo "函数$FUNCNAME::参数为空,返回"
rm -f ${rmafs}/locale$repo ${ramfs}/slocale$repo ${ramfs}/locale4del$repo

#ls -l $@ |awk '/^-/  {print $5"%"$NF}' >$ramfs/slocale$repo
#ls -l $@ |awk '/^-/  {print $NF}' >$ramfs/locale$repo
#ls -l $@ |awk '/^-/  {print "/"$NF"/d;t end"}END{print ":end"}' >$ramfs/locale4del$repo


ls -l $@ |awk '/^-/  {print $5"%"$NF>"slocale";print $NF>"locale";print "/"$NF"/d;t end">"locale4del"}'  &>/dev/null
mv slocale $ramfs/slocale$repo
mv locale $ramfs/locale$repo
mv locale4del $ramfs/locale4del$repo

echo  ":end">>$ramfs/slocale$repo
echo  ":end">>$ramfs/locale$repo
echo  ":end">>$ramfs/locale4del$repo

}

function downhtmldb()
{
local errnum re repo LDB_SECTION  err I
errnum=0
repo=
I=0
LDB_SECTION=()  
re=0
err=0
LDB_SECTION=( ${SECTION[@]} )
DB_SECTION=()
err=0
until [ "${#LDB_SECTION[@]}" = 0 ]
do
        for ((I=0;I<${#LDB_SECTION[@]};I++))
        do
        repo=${LDB_SECTION[$I]}
        rm -f index.html  $repo.db.tar.gz
        #echo "http://mirrors.easynews.com/linux/archlinux/$repo/os/$ARCH/">$ramfs/url
        echo "http://mirrors.lcuc.org.cn/archlinux/$repo/os/$ARCH/">$ramfs/url
        echo "http://mirrors.lcuc.org.cn/archlinux/$repo/os/$ARCH/$repo.db.tar.gz">>$ramfs/url
        #echo "http://mirrors.easynews.com/linux/archlinux/$repo/os/$ARCH/$repo.db.tar.gz">$ramfs/url
        wget -i $ramfs/url

        if [  -s $repo.db.tar.gz ] && [  -s index.html ]  ;then
        LDB_SECTION[$I]=
             DB_SECTION=( ${DB_SECTION[@]} $repo )
        cp  -f  index.html $STATU/$repo.html
        mv -f $repo.db.tar.gz $STATU/$repo.db.tar.gz

        fi
        done
LDB_SECTION=( ${LDB_SECTION[@]} )
if [ $((++errnum)) = 2 ] ;then
re=1
break
fi
done
unset I LDB_SECTION repo errnum  
return $re
}
function dbfile2html()
{
rm -f $ramfs/del4locale$repo.sed $ramfs/dgcdb
ls -l $ramfs/db$repo/ |awk '/^d/{print "s/^" $NF ".\\+pkg\\.tar\\.gz$/&/;t end"}END{print "/./d";print ":end"}'>$ramfs/dgcdb$repo
#ls -l $ramfs/db$repo/|awk '/^d/{print "/" $NF ".\\+\\.pkg\\.tar\\.gz$/d;t end"}END{print ":end"}'>$ramfs/db4dellocale

#sed -e's/"/\n/g'  $STATU/$repo.html |sed -e '/^.\+\.pkg\.tar\.gz$/!d' |tee >(sed -f
#$ramfs/dgcdb>${ramfs}/down${repo}) >( sed -f $ramfs/db4dellocale>$ramfs/del4locale$repo.sed)
#上述语句可以生成相应的文件,但down$repo文件在downlist中居然检测不到。但是事实上是存在的,将downlist的语句手动执行是有效的。估计与多进程有关。加上wait也无效果,改由下语句实现就安全了 ===还有一个命令针对在管道中使用大文件的,没有试
sed -e's/"/\n/g'  $STATU/$repo.html |sed -e '/^.\+\.pkg\.tar\.gz$/!d' >$ramfs/$repo.file  #由网页源码提取的文件单
sed -f $ramfs/dgcdb$repo  $ramfs/$repo.file >${ramfs}/down${repo}                                #除去数据库中没有的文件名
awk '{print "/"$1"/d;t end"}END{print ":end"}' ${ramfs}/down${repo} >$ramfs/del4locale$repo.sed
#sed -f $ramfs/del4locale$repo.sed $ramfs/locale$repo >$ramfs/old$repo
if [[ ! -s  {ramfs}/down${repo} ]];then
return 1
fi

#$ramfs/dgcdb用于删除数据库里没有的文件名,以保证正确下载
#$ramfs/db4dellocale用于删除旧,或多余的文件

#$ramfs/down$repo 是由SED以$ramfs/dgcdb命令经由数据库的文件名借助网页的源码中的文件名转换得到的服务器上的文件名,并删除数据库中没有的文件名
#$ramfs/del4locale$repo.sed用以生成删除多余的文件,在下载结束后使用

#将那些服务器上有, 而数据库里没有的文件名除掉:  以 $repo.db.tar.gz为基准下载文件,以保证结束**在下载,防止因服务器有而数据库里没有的文件,影响正常的结束


}
#删除多余的文件
function delold()
{
local linect  delfile

if [[ -s $ramfs/del4locale$repo.sed ]];then
  linect=`wc -l  "$ramfs/del4locale$repo.sed" `
  linect=${linect% *}
       if [[ $linect -lt 100 ]];then
       echo  "错误 ::来自::函数$FUNCNAME::行号:LINENO::请检查文件:del4locale$repo.sed">>$LOG
       return  1
       fi
else
echo "错误 ::来自::函数$FUNCNAME::行号:LINENO::请检查文件:del4locale$repo.sed">>$LOG
return  1
fi

read -r -a delfile<<<$(sed -f $ramfs/del4locale$repo.sed $ramfs/locale$repo)
if [[ "$1" = "test" ]];then
echo ${delfile[@]}
echo "旧文件数:合计:" ${#delfile[@]}
echo "来自::函数$FUNCNAME::行号:LINENO::回车键继续"
read
else

cd $DOWN/$repo/os/${ARCH}            #简单的,就只要下面三行就可以
rm -f  $delfile &>/dev/null
cd $oldpath
fi

unset  linect delfile
}

function downlist()
{
if [[ -f ${ramfs}/locale4del${repo} ]] && [[ -s   ${ramfs}/down${repo} ]];then
read -r -a list4down<<<$(sed -f ${ramfs}/locale4del${repo}   ${ramfs}/down${repo})
else
echo "文件不存在或空:${ramfs}/locale4del${repo}   ${ramfs}/down${repo}"
return 1
fi
#用于下载HTML的方式   down$repo由dbfile2html生成
#${ramfs}/locale4del$repo.sed  由localefile 生成

}
#调用参数数据库路径 当前$repo
#数据文件解压后在$ramfs ,一般在内存文件。有数据在数组name$repo size$repo md5$repo,并写回$TMP/db$repo/name$repo ....et.
function extrdb()
{
read  -r -a name4db<<<$(tar -xvzf $1 -C  $ramfs/db$repo/  |sed -e '/\/$/!d;t end;/\/$/{s/\/$//; t end};:end' )

}

function auto()
{
#没有使用,功能,判别本地的 $rep.db.tar.gz与源的是否一致。作为是否更新的条件(方法)
local repo
      
case $1 in
auto)
        for repo in ${SECTION[@]}
        do
        if [[ -f  $STATU/$repo.db.tar.gz  ]] && [[ -f $DOWN/$repo/os/$ARCH/$repo.db.tar.gz  ]];then
        a1=$($(md5sum  $STATU/$repo.db.tar.gz   )  |  sed 's/ \+$//')  
        a2=$(md5sum  $DOWN/$repo.db.tar.gz    | sed 's/ \+$//')
                      if [ "$a1" != "$a2" ]
                 then
                       SECTION1=(${SECTION[@]} $repo)  #不相符的repo加入到新的数组
                fi
        else
        SECTION1=(${SECTION[@]} $repo)  #不相符的repo加入到新的数组
        fi
        done
;;
autof)

;;
esac
unset repo
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-30 00:10:09 | 显示全部楼层
function md5()
{
local downpkg md5ok
[[ ! -n "$1" ]] && echo "函数$FUNCNAME::没有路径参数" && return 1

echo "md5">$ramfs/MD5
read -r -a downpkg<<<$(ls -l  $1/*.pkg.tar.gz |awk '/^-/ {print $NF}')
# 奇怪使用引号即错ls -l "$TMP/tmp$repo/*.pkg.tar.gz"
path=`pwd`
cd $1
getdbinfo downpkg  
#read -r -a md5ok<<<$(md5sum   $(ls -l *.pkg.tar.gz |awk '$1~/^-/  { print $5"%"$NF}'|sed -f  $ramfs/sizenamedb$repo.sed) $ramfs/MD5|sed -f  $ramfs/md5name4del$repo.sed)  
#好像这语句不行


md5sum   $(ls -l *.pkg.tar.gz |awk '$1~/^-/  { print $5"%"$NF}'|sed -f  $ramfs/sizenamedb$repo.sed) $ramfs/MD5|sed   's/\s\+/%/'>$ramfs/md5$repo
read -r -a md5ok<<<$(sed -f  $ramfs/md5name4del$repo.sed  $ramfs/md5$repo)
  

:<<EOF
#ls命令得到的文件表经awk生成size%filename形式,再由sed与数据库的信息比较,删除那些size不相符的文件名单(为了减少大size文件不相符的文件的md5计算时间),由md5sum计算md5,生成md5%filename形式的文件表,与数据库的信息比较,,删除不相符的,将得到相符文件的读入数组md5ok.数据库的文件名为不带-${ARCH}.pkg.tar.gz 或.pkg.tar.gz 即在判断时文件名+版本相符即认为是同一个文件。因为在$repo.db.tar.gz由于历史或其他原因,并不存在%FILENAME%,只有%NAME%,
%VERSION%,我们以%NAME%-%VERSION%识别一个文件。
sizenamedb$repo.sed,  md5namedb$repo.sed两个文件在getdbinfo函数中生成。downpkg为下载文件数组  
EOF
echo "#MD5检验::$repo: 路径:$DOWN/$repo/os/$ARCH::校验结果,不相符文件${#md5ok[@]} ;请查看文件$STATU/md5info.$repo."
echo "#MD5检验::$repo: 路径:$DOWN/$repo/os/$ARCH::校验结果,不相符文件${#md5ok[@]} ;请查看文件$STATU/md5info.$repo.">$STATU/md5info.$repo
echo ${md5ok[@]}|tr ' ' '\n' >>$STATU/md5info.$repo
cd $path


}


function program_auto()
{

local downfilelist path    ii DOWN_SECTION  counter  LEN
counter=0
echo "进入更新文件模块$FUNCNAME::"
echo "开始下载服务器上的数据库"
downhtmldb  &>/dev/null
if [[ $? != 0 ]];then
echo "FORM::函数$FUNCNAME::下载文件清单没有完成"
EXIT 1
fi
if [[  "${#DB_SECTION[@]}" = 0 ]];then
echo "函数$FUNCNAME:下载文件清单为空"
#增加一个计数器,统计错误次数
EXIT 2
fi
echo "准备下载{DB_SECTION[@]}"

#建立若干数组,对应SECTION,
#len=${SECTION[@]}

DOWN_SECTION=( ${DB_SECTION[@]} )
LEN=${#DB_SECTION[@]}


#1检查是否存在db.tar.gz,      有设置 check$repo=1
#2下载db.tar.gz              成功2
#3是否在$DOWN/$repo/os/${ARCH}/$repo.db.tar.gz 存在=3  

DOWN_SECTION=( ${DOWN_SECTION[@]} )
LEN=${#DOWN_SECTION[@]}

for ((ii=0;ii<${LEN};ii++))
do
rm -f $STATU/downfile$repo.log
repo=${DOWN_SECTION[$ii]}
STEP=step$repo
eval $STEP=0
counter=0

echo "开始下载:repo::"$STEP=${!STEP}
  
#本流程为:
#STEP-0
#检查$repo.db.tar.gz是否存在,no,下载,检查与本地源的是否一致,否,开始下载。  
#===================================================================
#注:命令参数-f,与此-auto有不同,是强制下载.db.tar.gz进行比较。比较所有的文件名和文件的大小。以此判断是否需要下载新的文件

#---------------------------------------------------------------------

#STEP-1
#解压数据库取得文件的列表,包括size,md5等,由size+文件名e,md5+文件名组成新的文件
#取本地的文件表,组成size+文件名的本地文件表
#由上两者得到要下载的文件(sed生成,效率比bash排序查找高)和多余的文件
#开始下载

#STEP-2
#通过数据库比较已下载文件验证是否有下载不成功的文件,如有即继续下载,直到完成所有文件的下载。转入STEP4
#STEP-3
#正常下载失败,改用rsync下载
#STEP4
#进行下载文件的MD5校验。删除不相符的文件,相符的文件转入库目录。转到STEP5
#STEP7-9
#下载退出。。
pp=0
until [[ ${!STEP} = [6-9]  ]]
do
if [[ $((pp++)) = 8  ]] ;then
echo  "函数$FUNCNAME:repo download error! 运行态$STEP=${!STEP} , skip $repo">>$LOG
eval $STEP=6
fi

STEP=step$repo
echo ${!STEP}
        case ${!STEP} in
        0)
        echo "SETP-0"
        echo "解压数据库"
        extrdb $STATU/$repo.db.tar.gz     &>/dev/null            # 解压库
        echo "制作服务器上的文件列表"
        dbfile2html
        echo "制作本地文件列表"
        localfile $DEST/$repo/os/${ARCH}/  #舍生成本地已有的pkg.tar.gz文件
        if [[ $? != 0 ]];then
        echo "错误提示 自函数$FUNCNAME::行号:LINENO::注意检查localfile 是否错误"
        fi
        echo "生成下载文件表单"
        downlist      
        if [[ $? != 0 ]];then
        echo "函数$FUNCNAME::行号:LINENO:检查错误;下载文件列表可能有问题"
        fi                               #生成下载文件数组list4down
        echo '需下载文件个数:'${#list4down[@]}   
             if [ "${#list4down[@]}" = 0 ]; then
              echo "不需要下载文件"
        cp $STATU/$repo.db.tar.gz $DOWN/$repo/os/$ARCH/
        [[ $? != 0 ]] && echo "警告:拷贝文件操作失败:函数$FUNCNAME行号$LINENO:cp $STATU/$repo.db.tar.gz DOWN/$repo/os/$ARCH/ "
        eval $STEP=9
        continue
        fi
        echo "开始下载文件"
        downfile  # 下载文件.注掉调 downfile 将跟着的eval $STEP=4改为eval $STEP=3,即可采用rsync更新  
        eval $STEP=4                                    #进入md5校验
       ;;

        2)
        echo "STEP-1"                                   #md5校验后进入此,
           eval  $STEP=2
        echo "检查是否已全部下载"
        localfile $DEST/$repo/os/${ARCH}/
        downlist
        if [ "${#list4down[@]}" = 0 ]; then             #没有需要下载的文件了
              echo "$repo:下载完成.正在删除多余的文件"
        delold                                #删除旧的文件
                if [[ $? = 0 ]]  ;then
                cp $STATU/$repo.db.tar.gz $DOWN/$repo/os/$ARCH/
                else
                echo "删除文件操作失败"
                echo "删除文件操作失败">>$LOG
               
        #LOCAL_SECTION=(${LOCAL_SECTION[@]})
                fi
        eval $STEP=9  
                     #正常结束
                DOWN_SECTION[$ii]=         #从下载表中除名
                continue
        fi
         if [[ $((++counter))  = 3 ]];then
         eval $STEP=6          #原定 $STEP=3,采用rsync ,但这也不是好的方法。如果程序有问题,可以采用,否则可多次下载

         echo $STEP=${!STEP}>>$LOG
         echo "尚未下载的文件">>$LOG
         echo   ${list4down[@]}>>$LOG
           # 总下载已到2次。如果是一个文件不能正常连接,也已
         continue
         fi
        echo "继续下载"
        downfile                                        #继续下载
        eval $STEP=4                                    #进行md5校验
       
        ;;       
        3)         
        echo "正常下载无法终止,尝试使用rsync下载"          # 多次下载仍不能终止下载,可能是设计思想不完整,也可能是原有的官方数据格式发生了变化,改用rsync进行更新
        do_rsync
        if [ "$?" != "0" ]; then
        echo "$repo:下载失败"                          
        eval $STEP=7                                   #rsync非正常结束
        else
        eval $STEP=8                                   #rsync正常结束
        fi
        DOWN_SECTION[$ii]=         #从下载表中除名
        #LOCAL_SECTION=(${LOCAL_SECTION[@]})
        ;;
             4)
         echo "STEP-4 进入MD5检验.时间较长,请等候。。。"
   
         echo "md5">$ramfs/MD5
         read -r -a downpkg<<<$(ls -l  $TMP/tmp$repo/*.pkg.tar.gz |awk '/^-/ {print $NF}')  &>/dev/null
# 奇怪使用引号即错ls -l "$TMP/tmp$repo/*.pkg.tar.gz"
        path=`pwd`
        cd $TMP/tmp$repo
        getdbinfo downpkg  
      #  read -r -a md5ok<<<$(md5sum   $(ls -l *.pkg.tar.gz |awk '$1~/^-/  { print $5"%"$NF}'|sed -f  $ramfs/sizenamedb$repo.sed)  $ramfs/MD5|sed -f  $ramfs/md5namedb$repo.sed)  

        md5sum   $(ls -l *.pkg.tar.gz |awk '$1~/^-/  { print $5"%"$NF}'|sed -f \
$ramfs/sizenamedb$repo.sed) $ramfs/MD5|sed   's/\s\+/%/'>$ramfs/smd5$repo




#>$ramfs/smd5$repo   \
# &>/dev/null
        read -r -a md5ok<<<$(sed -f  $ramfs/md5namedb$repo.sed  $ramfs/smd5$repo)

        echo $repo>>$STATU/downfile$repo.log
        echo "本次下载文件数">>$STATU/downfile$repo.log
        echo `ls  *.pkg.tar.gz `>>$STATU/downfile$repo.log
        echo "md5相符::${#md5ok[@]}">>$STATU/downfile$repo.log
        echo
        echo ${md5ok[@]}>>$STATU/downfile$repo.log
        


:<<EOF
#ls命令得到的文件表经awk生成size%filename形式,再由sed与数据库的信息比较,删除那些size不相符的文件名单(为了减少大size文件不相符的文件的md5计算时间),由md5sum计算md5,生成md5%filename形式的文件表,与数据库的信息比较,,删除不相符的,将得到相符文件的读入数组md5ok.数据库的文件名为不带-${ARCH}.pkg.tar.gz 或.pkg.tar.gz 即在判断时文件名+版本相符即认为是同一个文件。因为在$repo.db.tar.gz由于历史或其他原因,并不存在%FILENAME%,只有%NAME%,
%VERSION%,我们以%NAME%-%VERSION%识别一个文件。
sizenamedb$repo.sed,  md5namedb$repo.sed两个文件在getdbinfo函数中生成。downpkg为下载文件数组  
EOF
        
        mv ${md5ok[@]} $DOWN/$repo/os/$ARCH/  &>/dev/null
        rm -f *   &>/dev/null
        cd $path
        eval $STEP=2
      
        ;;
        [7-9])
        #脚本并不执行到这里
        DOWN_SECTION=( ${DOWN_SECTION[@]} )
echo $repo>>$LOG
echo "$STEP=${!STEP}">>$LOG
echo "${LOCAL_SECTION[@]}">>$LOG
;;
        *)
echo $repo>>$LOG
echo "$STEP=${!STEP}">>$LOG
echo "${DOWN_SECTION[@]}">>$LOG
break
;;
esac

done # until [ {!STEP} = [7-9]  ]



done

DOWN_SECTION=( ${DOWN_SECTION[@]} )
LEN=${#DB_SECTION[@]}

for ((ii=0;ii<$LEN;ii++))
do
repo=${DB_SECTION[$ii]}
STEP=step$repo
case ${!STEP} in
7)
echo "${SECTION[$ii]}下载rsync下载:失败"
;;
8)
echo "${SECTION[$ii]}下载rsync下载完毕"
;;
9)
echo "${SECTION[$ii]}下载成功"
;;
*)
echo "${SECTION[$ii]}没有编号$STEP=${!STEP}"
;;
esac


done
EXIT 0
unset downfilelist path  list  loop counter loop1 ii DOWN_SECTION  
}

#-------------------------------以上是功能流程函数---------------------------------
#------------------------------脚本从这里开始执行----------------
:<<BLOCK
这是注释1
设计思想:
正当性基于$repo.db.tar.gz数据库的正确性
1-采用由网页源码提取要下载文件的方法得到源文件表,与本地文件比较得到需要下载的文件。
2-解压数据库,取得源的软件的size,md5。由1,2得到3:
3-生成sieze+fiename  md5+filename的文件并排序,以便利用sed与本地文件进行比较,得到需要下载的文件文件和需要删除的文件。
  经过试验,使用sed的进行比较的效率比用bsah进行比较的效率要高。
4-生成本地文件,用于与3生成文件的进行比较
5-依由3,4得到的文件比较得到确定需要下载的文件表,
6-下载
实现上述功能是相对简单的,但要实现较复杂的,或说完美一点的功能就复杂很多了,如没有MD5校验,就简单得很,
BLOCK

:<<BLOCK
注释2,主要函数说明
1)初始化   
init
repo=community
echo "init"
2)下载db.tar.gz
#--------------------------------------------------------                       
extrdb $STATU   解压数据库
解压后的文件存在在$ramfs/tmp$repo,一般为ramfs文件系统,不保存,也可以提高读写速度  name4db  是$repo的 源的文件名的数组,对应于$ramfs/tmp$repo下的目录名,用于读目录下的文件信息。
$STATU 为数据库所在目录,由下载时存档,名称约定$repo.db.tar.gz                     
3)localfile  $DEST/$repo/os/$ARCH $TMP/tmp$repo/  
参数有两个,一是用来做源的文件目录$DEST/$repo/os/$ARCH,一个是下载的临时存档目录$TMP/tmp$repo/ ,后者的文件经md5检验后转入前者  
4)downlist:生成下载的文件表list4down数组
5)downfile:依据服务器url和downfile生成mirrors数组,由aria2c下载文件
6)getdbinfo 参数为要取文件信息的文件名数组。一般为要下载的文件列表数组。运行前必须先解压数据库。
7)getdb 采用rsync的方式下载$repo.db.tar.gz,现在没有使用。
#------------------------------------------------------------------------------------------

debug() 是一个简单的下载测试函数,主要验证各个函数的正确性。不带md5校验和下载完整性检验功能。
#--------------------------------------------------------------------------------------------
BLOCK

:<<BLOCK
注释3


BLOCK

function program_md5()
{
echo ""
local LOCAL_SECTION  repo LEN i
LOCAL_SECTION=(${SECTION[@]})
echo "来自::函数$FUNCNAME:: MD5检验:${SECTION[@]}"
LEN=${#LOCAL_SECTION[@]}

for (( i=0;i<${LEN};i++ ))
do
echo ""
cp  $DOWN/$repo/os/$ARCH/$repo.db.tar.gz $STATU/
repo=${LOCAL_SECTION[$i]}
echo "开始时间:`date`::正在校验:$repo"
extrdb $DOWN/$repo/os/$ARCH/$repo.db.tar.gz            
md5 $DOWN/$repo/os/$ARCH/
done
unset repo LOCAL_SECTION  LEN i
echo "结束时间:`date`"


}

function debug()
{

repo="core"
init
SECTION=( core )

        downhtmldb                                     #下载服务器上的文件名单源码及¥热破。$repo.db.tar.gz
repo=core
       

        extrdb $STATU/$repo.db.tar.gz                 # 解压库$repo.db.tar.gz
        dbfile2html                                  #将服务器上得到的的文件单与$repo.db.tar.gz比较,除掉$repo.db.tar.gz中没有的
                                                     #如果需要下载全部的,取文件$repo.file,代替down$repo,删掉某些语句即可
        localfile $DEST/$repo/os/${ARCH}/ $TMP/tmp$repo/  #生成本地已有的pkg.tar.gz文件
        downlist                                       #生成下载文件数组list4down
        echo ${list4down[@]}
        if [[ ${#list4down[@]} = 0 ]] ;then
        echo "没有文件下载"
        else
        echo "${#list4down[@]}共有文件要下载"
        echo "来自::函数$FUNCNAME::行号:LINENO::操作提示:回车继续:下一步:开始下载文件"
        downfile                                        # 下载文件没有md5检验 ,旧文件没有删除,需运行delold
        echo "下载完毕"
        fi
        echo "来自::函数$FUNCNAME::行号:LINENO::操作提示:回车继续:下一步:检查多余的旧文件"
        delold         test                                        #去掉参数test可删掉旧文件,
       

}
arghandl $@       #处理命令行参数
echo $act
main
`echo $act`
#$atc       #执行相关函数
echo  "done"
EXIT
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-30 00:22:53 | 显示全部楼层

发得太乱了,打包看吧

发得太乱了,打包看吧

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

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

本版积分规则

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