ProFTPd 验证完整上传
我在想,检查上传到FTP服务器是否成功有没有什么好的方法。
我现在用的系统有一个上传目录,里面为每个用户创建了子目录,文件就是上传到这些地方的。
这些目录里的文件都是临时的,处理完后就会被删除。
系统会遍历每个子目录和里面的新文件,对于每个文件,它会检查文件在10秒内是否有被修改。如果10秒内没有修改,系统就认为文件上传成功了。
我不太喜欢现在系统处理这些情况的方式,因为如果文件上传不完整,它会尝试处理这个文件并失败,而不是等着让用户继续上传,直到上传完成。对于小文件来说,这样可能还行,但如果文件很大,我希望能继续上传。
我也不喜欢系统在遍历目录和文件时的高CPU使用率,所以我使用了pyinotify,这样在文件写入时就能触发一个动作。我没有仔细看源代码,但我想它比现在的实现要优化得多(现在的实现比我描述的要复杂)。
不过,我还是需要检查文件是否成功上传。
我知道可以解析xferlog来获取所有成功上传的文件,比如:
awk '($12 ~ /^i$/ && $NF ~ /^c$/){print $9}' /var/log/proftpd/xferlog
这样的话,使用pyinotify就没必要了,因为我只要查看日志就能得到完整和不完整上传的路径。
所以我的解决方案是,在我的运行循环中检查xferlog,只处理完整的文件。
除非有更好的方法或者最佳实践?
这种方法有什么缺点吗?
我在一个Debian服务器上运行我的应用,proftpd也安装在同一台服务器上。而且,我对发送文件的客户端没有控制权。
2 个回答
如果你的pure-ftpd安装时使用了--with-uploadscript
这个选项,那么你可以使用pure-uploadscript。
这个功能的作用是在每次上传完成后,自动运行一个指定的脚本。
- 首先,把CallUploadScript设置为“yes”。
- 然后,创建一个脚本,里面可以写个命令,比如
touch /tmp/script.sh
,这个命令的意思是创建一个空的脚本文件。 接下来,在这个脚本里写入代码。在我的例子中,这个脚本会把文件重命名,并在文件名之前加上“.completed”:
#!/bin/bash fullpath=$1 filename=$(basename "$1") dirname=${fullpath%/*} mv "$fullpath" "$dirname/completed.$filename"
然后运行
chmod 755 /tmp/script.sh
,这样可以让pure-uploadscript有权限执行这个脚本。最后,运行命令
pure-uploadscript -B -r /etc/pure-ftpd/uploadscript.sh
来启动这个上传脚本。
现在,每次上传完成后,/tmp/script.sh
都会被自动运行。
在查看proftpd的文档时,我发现了这个链接:http://www.proftpd.org/docs/directives/linked/config_ref_HiddenStores.html
HiddenStores指令允许进行两步文件上传:文件会先以“.in.filename.”的形式上传,等上传完成后再改名为“filename”。这样做可以确保上传的完整性,避免出现1)上传不完整的情况,以及2)在文件还在上传时被使用。
如果你能控制proftpd,这应该是解决问题的“更好方法”,因为它会为你处理所有的工作——你可以放心地认为,任何不以.in.
开头的文件都是上传完成的文件。此外,你还可以在某个清理脚本中安全地删除那些在一段时间内没有活动的孤立.in.*
文件。