首页 > 代码库 > 一个开源项目中用到的bash shell脚本

一个开源项目中用到的bash shell脚本

请看系统鸟瞰图:

  因为笔者所在的地方并无可用的宽带和Wifi,所以暂且只能采用上图中的联网方法,使用ssh走手机GPRS流量的方法进行远程操作云风典藏官网的服务器,以完成所有任务。
  关于云风典藏的更多信息,请看文章《四个月的隐居和一个新的开源项目——云风典藏》。


第一步:SSH安全设置
  服务器现在由我们全部负责,远程登录的安全为重中之重。
  1.创建一普通用户,以后只使用此用户来远程登录系统;
  2.修改root密码;
  3.修改sshd的配置:

1 #vim sshd_config file2 Port 11113 Port 333334 Port 478735 AllowUsers username6 MaxAuthTries 2

  修改sshd的默认端口22,增加多个自定义端口,免得被人打扰而使得自己登不上服务器,只允许username用户通过sshd登录系统。
  修改完毕,保存,重启sshd。
 
第二步:开始面向目标服务器的抓取工作
  写好脚本,验证无误。

$nohup bash grab.sh &>grab.sh.log &

  使用nohup来免疫当父进程退出时发来的hangup信号,使得任务真正的能够后台运行,即使当前的ssh连接因为GPRS网络不稳定(经常会遇到)而意外中断,仍然不会影响到我们的grab任务。
  另外提醒一点,刚开始我使用并发数十个进程同时抓取目标(因为任务量很大,为了节约时间),最后才发现很多子任务都失败了,这肯定是因为对方的Web服务器设置了单个IP并行连接的限制而导致的,于是我更改为单进程抓取,出错率显著的降低了。
  这时候就可以去睡觉了,明天早上再看看grab日志有无异常。
  第二天早上,当任务完成后:

$ ls -Slr *html | more

  查看单个任务出错的情况。

$ find ./*html -size -5557c >error.list

  找到阈值,使用find将所有出错的任务文件名称打印到一个文件里。  

  第二次再专门针对出错的任务进行抓取,正常情况下出错的概率很低,所以这里的任务量就会很小。    

  如果有多个目标服务器的抓取任务的话,可以采用多个任务同时进行抓取的方法,因为很多时候,是对方服务器跟不上我们的请求,而非我们的网络带宽不够大。

 

第二步:对抓取到的html与小图片进行处理  

 find、sed、awk、grep这四把利器对于一般的文本处理要求毫无压力。

$grep -o [一-龥] 

  过滤出utf-8中的20902个汉字

$grep -oP re

  grep的-P即--perl-regexp,正则表达式的断言绝对好用 :)

#!/bin/bashls *html | while read ido    buf=`cat $i`    echo $buf | while read j    do        #process......    donedone

  将很多字符缓存到bash的变量中,有时候很方便 :) 

$ iconv -c -f utf-8 -t gbk

  windows默认gbk,而linux默认utf-8,所以上述命令很常用。
  其选项-c从输出中忽略无效的字符,如果不使用此选项当iconv遇到输入的非法字符时将会出错退出,导致文件流转码被中途腰斩。

$ 7za x -r dir.7z$ 7za a -r ety.7z ety/

  当需要在linux与windows上来回传送文件时,中文的文件名很可能会乱码,原因已在上面阐述了。而7za默认能保存和转换文件名的编码,使得文件名乱码事件不会发生。另外,7z号称最强压缩算法,而且是免费的。

 

第三步:文件名称加密转码 请看下图:

  有时候我们并不想将我们的文件访问路径直接给用户,而是想转成一组无规律可循的编码表示,以防止用户进行迭代抓取(:也许还有其他原因:)
  这时候我们希望将完整的文件名路径如:

/img/hanzi/xiaozhuan/9053.gif

  单一可逆的映射到如   

/img/TI87980FHGJHK899B.gif

  的路径上,这时候就需要一些转换了 :)

   上述为关键详细过程,下面提供一个随机加密模组生成bash shell script:

#####隨機打散數組 随机打散数组ara=0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZwhile true do    if [ -z "$ara" ]    then         break    fi    b=$((RANDOM%62))    #echo $b    b="${ara:${b}:1}"    #echo "<$b>"    if [ -z "$b" ]    then         continue    fi    ara=${ara/${b}/}    echo $bdone | tr -d \necho ""# output:$C8O1Fb0oPlkmzycSpZMuEtXBwgLnQUeHvArRDf67as9I5xJdWNjhi3TVGqK42Y

  上述算法思想很有趣,感兴趣的可以仔细看一下:)
  全部实现代码如下:

 1 function yunencode() { 2  3   base64 | tr 0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ C8O1Fb0oPlkmzycSpZMuEtXBwgLnQUeHvArRDf67as9I5xJdWNjhi3TVGqK42Y | 4   sed s|A|AA|g | sed s|+|AB|g | sed s|/|AC|g | sed s|=|AD|g |  5   sed s|.*$|&AE|g | tr -d \n 6 } 7  8  9 function yundecode() {10 11     ###########12     declare ycpre=""13     declare ycnow=""14     declare ycn=015     sed s|.|&\n|g | while read ycnow16     do17         #echo -n 1 $ycnow 118         #echo yun:$ycpre:ycnow19         ycn=$((ycn+1))20             #echo -n "$ycpre$ycnow"21             if [ "$ycpre" = "A" ]22             then23               if [ "$ycnow" = "A" ]24               then25                   echo -n A26                   ycpre=‘‘27               elif [ "$ycnow" = "B" ]28               then29                   echo -n +30                   ycpre=‘‘31               elif [ "$ycnow" = "C" ]32               then33                   echo -n /34                   ycpre=‘‘35               elif [ "$ycnow" = "D" ]36               then37                   echo -n =38                   ycpre=‘‘39               elif [ "$ycnow" = "E" ]40               then41                 echo ""42                 ycpre=‘‘43               else44                   echo -n A45                 echo -n $ycnow46                 ycpre=‘‘47                 fi48             else49                 if [ "$ycnow" = A ]50                 then51                     ycpre=A52                 else53                     ycpre=‘‘54                     echo -n $ycnow55                 fi56             fi57         #echo ""58     done | tr C8O1Fb0oPlkmzycSpZMuEtXBwgLnQUeHvArRDf67as9I5xJdWNjhi3TVGqK42Y  0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ 59     | base64 -d60 }61 62 63 function yunencode0win() {64     yunencode | sed s|0|00|g | sed s|[a-z]|0&|g | tr a-z A-Z 65 }66 67 function yundecode0win() {68     declare ycpre=""69     declare ycnow=""70     sed s|.|&\n|g | while read ycnow71     do72         if [ "$ycpre" = "0" ]73         then74             if [ "$ycnow" = "0" ]75             then76                 echo -n "0"77                 ycpre=""78             elif echo "$ycnow" | grep -Po [A-Z] &>/dev/null79             then80                 ycnow=` echo "$ycnow" | tr A-Z a-z `81                 echo -n "$ycnow"82                 ycpre=""83             else84                 echo -n "0"85                 echo -n "$ycnow"86                 ycpre=‘‘87             fi88         else89             if [ "$ycnow" = "0" ]90             then91                 ycpre=092             else93                 ycpre=‘‘94                 echo -n "$ycnow"95             fi96         fi97     done | yundecode98 }
View Code

  上述代码两次写成,所以很多都可以在进行速度优化的,比如yundecode0win对应的两个状态机可以简化为一个,不过逻辑稍微复杂些而已。
  yunencode0win与yundecode0win并没有实现DES3二进制加密的部分,因为使用管道配合openssl即可轻松实现:

$ dd if=a.bin | openssl des3 | yunencode0win  $ echo yunencoded-msg | yundecode0win | openssl des3 -d | dd of=a.bin.new

  这里有两把钥匙,一把是你的openssl password,一把是你的随机tr模板,如果你觉得一次DES3加密太过简单,你可以使用多轮多种加密算法辗转处理......

 

第四步:从远方的服务器上传文件到网络云盘

  使用bypy.py在服务器上upload文件到百度云盘,这是最后一步了。
  如果你想要加密你的文件:

$ dd if=v1.01.7z | openssl des3 | dd of=v1.01.7z.abc

  另外7z也支持加密压缩。

 

  感谢你花时间来阅读这篇文章!  

附录:

  《从VPS上传文件到百度网盘》、《四个月的隐居和一个新的开源项目——云风典藏》

 

一个开源项目中用到的bash shell脚本