在Linux上监视和ftp新添加的文件 - 修改现有代码

时间:2016-02-14 00:10:57

标签: bash

操作系统是第7期,我有一个小应用程序来实现以下功能: 1.从config.ini中读取信息:

# Configuration file for ftpxml service
# Remote FTP server informations
ftpadress=1.2.3.4
username=test
password=test

# Local folders configuration
# folderA: folder for incomming files
folderA=/u02/dump

# folderB: Successfuly transfered files are copied here
folderB=/u02/dump_bak

# retrydir: when ftp upload fails, store failed files in this 
# directory
retrydir=/u02/dump_retry
  1. 监控文件夹A.如果A中有新添加的文件,请执行步骤3.

  2. 按照创建时间的顺序将这些新文件Ftp到远程ftp服务器,上传完成后,将上传的文件复制到文件夹B并删除文件夹A中的相关文件。

  3. 如果ftp失败,请将相关文件存储在retrydir中,然后尝试ftp。

  4. 记录日志文件中的每个操作。

  5. 应用程序的详细设置说明:

    安装ncftp软件包:yum install ncftp -y,它不是服务也不是守护进程,只是一个客户端工具,在bash文件中为ftp目的调用。

    使用vi:config.ini自定义这些文件以适合您的设置 ,ftpmon.path和ftpmon.service

    将ftpmon.path和ftpmon.service复制到/ etc / systemd / system /,将config.ini和ftpxml.sh复制到/ u02 / ftpxml /,运行:chmod + x ftpxml.sh

    启动监控工具 sudo systemctl启动ftpmon.path 如果要在引导时启用它,只需输入:sudo systemctl enable ftpmon.path

    设置cron任务以清除排队的文件(添加选项-p)

    * / 5 * * * * /u02/ftpxml/ftpxml.sh -p

    现在应用似乎运行良好,除了特殊情况: 例如,当我们在文件夹A中连续放置几个文件时,在短时间内一个接一个地放入1.txt,2.txt和3.txt ......我们通常会找到1.txt ftp,但是即将到来的文件无法ftp仍然保留在文件夹A下。 现在我要解决这个问题。我想错误可能是由于:在为第一个文件执行ftp时,可能已经在文件夹A下创建了第二个文件。因此代码无法关心第二个文件。 下面是ftpxml.sh的代码:

    #!/bin/bash
    
    # ! Please read the README.txt file !
    
    # Copy files from upload dir to remote FTP then save them
    # to folderB
    
    # look our location
    SCRIPT=$(readlink -f $0)
    # Absolute path to this script
    SCRIPTPATH=`dirname $SCRIPT`
    PIDFILE=${SCRIPTPATH}/ftpmon_prog.lock
    
    # load config.ini
    if [ -f $SCRIPTPATH/config.ini ]; then
       source $SCRIPTPATH/config.ini
    else 
       echo "No config found. Exiting"
    fi
    
    # Lock to avoid multiple instances
    if [ -f $PIDFILE ]; then
      kill -0 $(cat $PIDFILE)  2> /dev/null
      if [ $? == 0 ]; then
        exit
      fi 
    fi
    
    # Store PID in lock file
    echo $$ > $PIDFILE 
    
    # Parse cmdline arguments 
    while getopts ":ph" opt; do
      case $opt in
        p)
          #we set the purge mode (cron mode)
          purge_only=1
          ;;
        \?|h)
          echo "Help text" 
          exit 1
          ;;
      esac
    done
    
    # declare usefull functions
    
    # common logging function
    function logmsg() {
       LOGFILE=ftp_upload_`date +%Y%m%d`.log
       echo $(date +%m-%d-%Y\ %H:%M:%S) $* >> $SCRIPTPATH/log/${LOGFILE}
    }
    
    # Upload to remote FTP
    # we use ncftpput to batch silently
    # $1 file to upload $2 return value placeholder
    function upload() {
    
      ncftpput -V -u $username -p $password $ftpadress /prog/  $1
    
      return $?
    }
    
    function purge_retry() {
      failed_files=$(ls -1 -rt ${retrydir}/*)
      if [ -z $failed_files ]; then
         return
      fi
      while read line
      do
            #upload  ${retrydir}/$line 
            upload  $line 
            if [ $? !=  0 ]; then
               # upload failed we exit
               exit
            fi
    
            logmsg File $line Uploaded from ${retrydir}
            mv $line $folderB 
            logmsg File $line Copyed from ${retrydir}
      done <<< "$failed_files"
    }
    
    # first check out 'queue' directory
    purge_retry
    
    # if called from a cron task we are done
    if [ $purge_only ]; then
      rm -f $PIDFILE
      exit 0
    fi
    
    # look in incoming dir
    new_files=$(ls -1 -rt ${folderA}/*)
    while read line
    do
        # launch upload 
        if [ Z$line == 'Z' ]; then
          break
        fi
        #upload  ${folderA}/$line
        upload  $line
        if [ $? == 0 ]; then
        logmsg File $line Uploaded from ${folderA}
    
        else 
    
        # upload failed we cp to retry folder
          echo upload failed
          cp $line $retrydir
        fi
         # don't care upload successfull or failed, we ALWAYS move the file to folderB
        mv $line $folderB
        logmsg File $line Copyed from ${folderA}
    
    done <<< "$new_files"
    
    # clean exit
    rm -f $PIDFILE
    exit 0
    
    下面的

    是ftpmon.path的内容:

    [Unit]
    Description= Triggers the service that logs changes.
    Documentation= man:systemd.path
    
    [Path]
    # Enter the path to monitor (/u02/dump)
    PathModified=/u02/dump/
    
    [Install]
    WantedBy=multi-user.target
    

    以下是ftpmon.service的内容:

    [Unit]
    Description= Starts File Upload monitoring
    Documentation= man:systemd.service
    
    [Service]
    Type=oneshot
    
    #Set here the user that ftpmxml.sh will run as
    User=root
    
    #Set the exact path to the script
    ExecStart=/u02/ftpxml/ftpxml.sh
    
    
    [Install]
    WantedBy=default.target
    

    先谢谢,希望任何专家都能给我一些建议。

1 个答案:

答案 0 :(得分:0)

当你从A中删除成功传输的文件时,你可以在A中留下传输错误的文件。所以我只处理一个文件夹中的文件。

按创建时间

列出您的文件
 find -type f -maxdepth 1 -print0 | xargs -r0 stat -c %y\ %n | sort

如果您想要包含隐藏文件或 - 如果不想 -

 find -type f -maxdepth 0 -print0 | xargs -r0 stat -c %y\ %n | sort

你会得到像

这样的东西
2016-02-19 18:53:41.000000000 ./.dockerenv
2016-02-19 18:53:41.000000000 ./.dockerinit
2016-02-19 18:56:09.000000000 ./versions.txt
2016-02-19 19:01:44.000000000 ./test.sh

现在剪切文件名(或使用xargs -r0 stat -c %n如果文件按名称而不是时间戳排序并不重要)和

  • 进行转移
  • 检查成功
  • 将成功转移的文件移至B

如上所述,在某些情况下,新存储的文件无法成功传输。这可能是在您开始传输后进一步写入文件的情况。因此,将时间戳过滤至少一段时间。将-mmin -1添加到&#34;以及至少一分钟的&#34;

的查找语句中
find -type f -maxdepth 0 -mmin -1 -print0 | xargs -r0 stat -c %n | sort

如果您不想使用分钟文件时间,则必须检查文件是否仍处于打开状态:lsof | grep ./testfile但如果您的文件系统中有tmpfs,则可能会出现问题

lsof | grep ./testfile
lsof: WARNING: can't stat() tmpfs file system /var/lib/docker/containers/8596cd310292a54652c7f50d7315c8390703b4816442146b340946779a72a40c/shm
      Output information may be incomplete.
lsof: WARNING: can't stat() proc file system /run/docker/netns/fb9323486c44
      Output information may be incomplete.

因此,将%s添加到stats语句中以在几秒钟内检查文件大小两次,如果它是常量,则可以写入文件完成。可能,因为写入过程可能会停滞。