shell 实现监听本地目录,并将完整的文件上传到ftp或本地另一个目录

       这个脚本是我第一次接触shell写的脚本,当时是公司提的一个小需求,我记得写这个脚本的时候我是以一个实习生的身份刚进公司两三天。当时的我查了将近一个星期的百度还是没能找到一个符合我这个需求的脚本。那个时候才发现原来有些问题并不是直接百度便能找到符合自己需求的源码,直接ctrl C 、ctrl V 就解决了,最后也是公司大佬们一点一滴的指导才勉强写完了这个脚本。现在马上实习快结束了,所以想写播客记录下自己的实习生活。

        实现功能:定时的去遍历自己监听的目录,当出现文件时,判断其完整性,如果文件完整便将其上传到指定的ftp目录上,如果文件不完整则先不处理,等到下次遍历到的时候其完整再处理,现阶段只支持上传文件,如果监听目录有子目录的情况,脚本可能会报错(暂时不支持)。

        一些实现的方法:

        1. 定时的遍历:我这里选用的是linux 服务器自带的crontab 定时任务管理器。

        2. 完整性判断:因为文件的真实来源我们并不知道,所以无法获取文件最初的md5值,所以这里我用了比较“直板”的方法,使用了文件的最后修改时间去判断,如果文件属于一个上传状态,那个其最后修改时间一定是会刷新的。

        3. 每次上传文件都会去尝试连接ftp,不会出现当ftp突然挂了,遍历到监听文件完整后去执行上传操作,最后删除监听目录的文件,导致文件丢失。

        shell代码实现:脚本名称(upload.sh)

#!/bin/bash
## 用于将文件上传到ftp

##连接ftp的函数
function ftpConnectTest(){
ftp -n -v <<EOF
  open ${1} ${2}
  user ${3} ${4}
  bye
EOF
}

##判断文件夹存不存在
function ftpCheckDir(){
ftp -n -v <<EOF
   open ${1} ${2}
   user ${3} ${4}
   cd ${5}
   bye
EOF
}

## 将指定目录的文件上传到ftp
function upload_file_ftp() {
  src=$1
  ip=$2
  port=$3
  username=$4
  password=$5
  target=$6
  connect_record=/var/log/synchronismfile_log/ftpconnect.log
  mkdir_record=/var/log/synchronismfile_log/mkdirrecord.log
  upload_record=/var/log/synchronismfile_log/fileupload.log
##遍历源目录
  for file in `ls ${src}`
do
  #判断遍历到的是不是文件夹
  if [ -d $1"/"$file ]; then
    cat /dev/null > ${mkdir_record}
    ftpCheckDir $ip $port $username $password $target"/"$file >> ${mkdir_record}
    #判断是否登录成功
    if [ `grep -c 'Login successful.' ${mkdir_record}` -eq 0 ]; then
         if [ `grep -c 'User logged in, proceed.' ${mkdir_record}` -eq 0 ]; then
              echo "连接ftp服务器失败,请查看是否网络原因!">>/var/log/synchronismfile_log/syncfileerror.log
              exit 1
         fi
    fi
    ##连接出现两种情况,一个是ftp 一个是sftp
    if [ `grep -c 'Failed to change directory.' ${mkdir_record}` -eq 1 ]; then
        {
ftp -v -n <<EOF
   open $ip $port
   user $username $password
   cd $target
   mkdir $file
   bye
EOF
        }
    elif [ `grep -c 'No such directory.' ${mkdir_record}` -eq 1 ]; then
 {
ftp -v -n <<EOF
   open $ip $port
   user $username $password
   cd $target
   mkdir $file
   bye
EOF
        }
    else
        echo "ftp目录存在!"
    fi
    #继续递归遍历
    upload_file_ftp $src"/"$file $ip $port $username $password $target"/"$file
  fi
  #如果遍历到的是文件,文件完整则上传,文件不完整则不上传
  ##上传最后修改时间在10秒前的文件
  if [ -f $src"/"$file ]; then
    ##ftp连接测试挂掉了我直接给你退出了
  cat /dev/null > ${connect_record}
  ftpConnectTest $ip $port $username $password >> ${connect_record}
   if [ `grep -c 'Login successful.' ${connect_record}` -eq 0 ]; then
         if [ `grep -c 'User logged in, proceed.' ${connect_record}` -eq 0 ]; then
              echo "连接ftp服务器失败,请查看是否网络原因!">>/var/log/synchronismfile_log/syncfileerror.log
              exit 1
         fi
    fi

   last_update_time=`stat -c %Y $1"/"$file`
   current_time=`date +%s`
   echo "当前时间:"$current_time
   echo "文件最后修改时间: "$last_update_time
   echo "两者时间之差:"$[ $current_time - $last_update_time ]
   filename1=$(basename "$file")
   ttt=${filename1: -5}
if [ $ttt != _temp ]; then
   if [ $[ $current_time - $last_update_time ] -gt 3 ]; then
       filename=$(basename "$file")
       echo "文件名:"$filename
       ##判断文件名是否存在文件上传目录中
       if [ `grep -c $filename $upload_record` -eq 0 ]; then
         echo "文件上传记录中没有"$filename"文件将要开始上传"
         echo $filename >> $upload_record
ftp -v -n <<EOF
   open $ip $port
   user $username $password
   lcd $src
   cd $target
   binary
   hash
   prompt
   put $file
   bye
EOF
         rm -rf $src"/"$file
         sed -i "/$filename/d" /var/log/synchronismfile_log/fileupload.log
       fi
    else
       echo "文件不完整"
  fi
fi
       fi

done
}

##主函数
echo "upload.sh文件上传脚本执行"
starttime=`date +'%Y-%m-%d %H:%M:%S'`
    ##被监听目录
    src=$1
    ##目标目录
    bak=$2
    ##对传入的ftp进行截取
    userandpwd=${bak#*//}
    userpwd=${userandpwd%@*}
    user=${userpwd%:*}
    pwd=${userpwd#*:}
    urlandport=${userandpwd##*@}
    ip=${urlandport%:*}
    portandsrc=${urlandport#*:}
    port=${portandsrc%%/*}
    target=/${portandsrc#*/}
    ##在/var/log 目录下创建 synchronismfile_log目录,用于存放各种日志
    if [ ! -d "/var/log/synchronismfile_log" ]; then
      `mkdir /var/log/synchronismfile_log`
    fi
    if [ ! -d $src ]; then
      echo "本地源目录不存在,请先创建源目录">>/var/log/synchronismfile_log/syncfileerror.log
      exit 1
    fi
    ##创建记录文件上传名字的日志
    if [ ! -f "/var/log/synchronismfile_log/fileupload.log" ]; then
        `touch /var/log/synchronismfile_log/fileupload.log`
    fi
    ##用于记录日志
    connect_record=/var/log/synchronismfile_log/ftpconnect.log
    cat /dev/null > ${connect_record}
   ##ftp连接测试
   ftpConnectTest $ip $port $user $pwd >> ${connect_record}
   if [ `grep -c 'Login successful.' ${connect_record}` -eq 0 ]; then
         if [ `grep -c 'User logged in, proceed.' ${connect_record}` -eq 0 ]; then
              echo "连接ftp服务器失败,请查看是否网络原因!">>/var/log/synchronismfile_log/syncfileerror.log
              exit 1
         fi
    fi
   ##调用文件上传函数
    upload_file_ftp $src $ip $port $user $pwd $target
endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s);
end_seconds=$(date --date="$endtime" +%s);
echo "脚本执行结束,运行时间: "$((end_seconds-start_seconds))"s"

 

脚本调用方法:

上传到ftp:  ./upload.sh /home/test ftp://ftptest:123456@ip:port/testB

  上传到本地另一个目录:./upload.sh /home/test /home/testB

参数说明:/home/test :本地要监听的文件目录(脚本运行前得先建立)

                  ftp://用户名:密码@ip:port/testB:testB 上传到ftp的目录(也需先存在)

                  /home/testB: 要将脚本拷贝到的本地另一个目录(目录需先存在)

 

说明:如果要上传的文件过于珍贵,需自己先备份,脚本并不能保证百分百将文件不造成文件丢失

当然如果各位小伙伴,还有更好更安全的实现方式,欢迎大家来讨论

PS:如果有需要实时监听并上传的,大家可以尝试下inotify-tools工具去监控。这个我也写过一版,不过可能是我基础不行,还是哪里的逻辑出了问题,在监听上传时会导致服务器很卡,如果大家能找到这个的解决方案,也希望能告诉我下。

 

 

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值