Split 在 bash 中表现得很奇怪

Split 在 bash 中表现得很奇怪

尝试将 split 与 inotifywait 一起使用,当从 ftp 服务器创建文件时,它基本上会拆分文件。

#!/bin/bash

TARGET=/home/test-directory/incoming
SPLITTED=/home/test-directory/incoming/splitted
PROCESSED=/home/test-directory/incoming/processed
LOGFILE=/var/log/inotify-ftp.log

inotifywait -m -e create -e moved_to --format "%f" $TARGET \
        | while read FILENAME
                do
                        echo Detected $FILENAME >> $LOGFILE
                        echo Splitting $FILENAME >> $LOGFILE
                        split -d -l 1000 "$TARGET/$FILENAME" "$SPLITTED/$FILENAME"
                        #/usr/bin/split -d -l 1000 /home/test-directory/incoming/test-file.csv /home/test-directory/incoming/splitted/test-file.csv
                        mv "$TARGET/$FILENAME" "$PROCESSED/$FILENAME"
                        echo Completed splitting $FILENAME >> $LOGFILE
                done

因此,下面的代码在单独执行时工作正常。上面的脚本应该做同样的事情,但它创建了第一个只有几百行的分割文件。

#/usr/bin/split -d -l 1000 /home/test-directory/incoming/test-file.csv /home/test-directory/incoming/splitted/test-file.csv

知道吗,发生了什么事?

答案1

这是因为文件在创建时长度为零。有一个竞争条件,其中 split 计算出文件的大小,并决定如何分割它,而 ftp-server 很高兴地一直让它变得更大。

明智的做法是建立一种机制,让分割等待文件完全到达后再开始读取。通常,循环统计文件,直到它在前一分钟不再增长。

答案2

正如已经解释过的别处当文件(刚刚)创建时触发create事件,而不引用正在添加的内容。将事件inotifywait更改create为,close_write以便在文件传输服务关闭文件之前不会触发:

inotifywait -m -e close_write -e moved_to --format "%f" "$TARGET"

您还应该构建一些错误处理功能,以便您的进程可以区分完全传输的文件和中途中断的文件。这可能是检查文件内容的有效性,或者使用tmp发送者在成功传输时重命名文件时删除的后缀来传输文件,等等。

最后,作为良好的编码实践,请记住在使用变量的任何地方都用双引号引起来。

相关内容