尝试将 split 与 inotifywait 一起使用,这基本上会在从 ftp-server 创建文件时拆分文件。
#!/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
任何想法,发生了什么?
那是因为文件在创建时是零长度的。有一个竞争条件,其中 split 计算出文件的大小,并决定如何拆分它,而 ftp-server 一直在高兴地让它变大。
明智的做法是建立一种机制,让拆分在开始读取文件之前等待文件完全到达。通常,在循环中统计文件,直到它在前一分钟没有增长。
正如其他地方所解释的那样,当文件(刚刚)创建时触发
create
事件,不引用添加的内容。将事件inotifywait
更改为,以便在文件传输服务关闭文件之前不会触发:create
close_write
您还应该构建一些错误处理,以便您的进程可以区分完全传输的文件和中途中断的文件。这可能是检查文件内容的有效性,或者通过
tmp
发送者在成功传输时重命名文件后删除的后缀来传输文件等。最后,作为良好的编码习惯,请记住在使用它们的任何地方都用双引号引起来。