您为什么不使用某种自动化过程(例如使用 cron)为您执行同步?
您可以让 cron 作业监视“投递箱”目录(或多个目录),然后它可以运行脚本为您执行复制。
或者,您可以让用户提交带有一些元数据的文件,以便在文件上传后更好地路由文件。
简单地说,永远不要让用户“选择”它的去向,而是让他们告诉你“它的用途”,然后让你的脚本“知道”事情的去向以及如何将它们带到那里。
这是一个相当简单的网络应用程序,即使只使用一些 perl CGI 或其他什么。后端管道也很简单。
回复评论...
如果您有一个执行上传到 CGI 的 Web 应用程序,那么在文件完全上传之前,您通常甚至无法“控制”请求。有点取决于您使用的服务器端技术。无论如何,当文件完全上传时,使用网络应用程序很容易“知道”。然后,您的同步过程可以仅依靠元数据来实际对文件进行工作,并且在将文件移动到适当的暂存区域等之前,您不会创建元数据。
如果您只是使用 FTP 或 scp 将文件复制到暂存目录,那么解决方案有两个有两个进程。第一个监视传入目录,第二个实际复制文件。
第一个过程可以简单地如下所示:
cd /your/upload/dir
ls -l > /tmp/newfiles
comm -12 /tmp/lastfiles /tmp/newfiles > /tmp/samefiles
filelist=`awk '{print $9}' /tmp/samefiles`
mv $filelist /your/copy/dir
mv /tmp/newfiles /tmp/lastfiles
这像这样工作:
- 获取传入上传目录中的当前文件列表。
- 使用 comm(1) 获取自上次运行进程以来未更改的文件。
- 使用 awk(1) 获取未更改的文件名。
- 使用 mv(1) 将文件移动到您的“暂存”目录。
- 最后,它获取当前文件列表,并使其成为下一次运行的最后一个列表。
这里的魔力是 comm(1)。'comm -12 filea fileb' 为您提供一个文件,其中包含两个文件之间相同的行。如果有新文件进来,那么它的大小会在上传时改变,所以当你在下一分钟运行 'ls -l' 时,它的行将与新行不匹配——大小(最小)会不同. 因此,comm 只会查找日期、文件名和大小未更改的文件。一旦你有了那个列表,剩下的就很简单了。
此过程的唯一假设是您的文件名中没有空格(因此 awk 可以轻松地从列表中获取文件名)。如果您允许空格,您将需要一个更聪明的机制来将“ls -l”行转换为文件名。
此外,'mv $filelist /your/copy/dir' 假定文件名中没有空格,因此也需要对其进行修改(您可以将其滚动到 awk 脚本中,让它进行 system() 调用,也许)。
第二个过程也很简单:
cd /your/copy/dir
for i in *
do
sync $i
mv $i /your/file/youve/copied/dir
done
同样,这里的“文件名中没有空格假设”。此过程依赖于您编写的“做正确的事”的同步 shell 脚本。这留给读者作为练习。
同步后,它将文件移动到另一个目录。那里显示的所有文件都已正确“同步”。您也可以简单地删除该文件,但我倾向于不这样做。我可能会将该目录放在“删除一周以上的文件”程序中。这样,如果您遇到问题,您仍然可以在某个地方恢复原始文件。
这东西很简单,但也很健壮。
只要第一个进程的运行速度比上传“慢”(即如果你连续运行两次,你确信文件大小至少会改变),那么运行时间可以是每 1 分钟,每小时,每天,随便。至少,它可以安全地重新启动,并且可以自我恢复。
第二个过程的阴暗面是,如果您的同步过程比您的计划 cron 花费的时间更长。如果您每分钟运行一次,并且运行时间超过一分钟,那么您将有两个进程复制相同的文件。
如果您的同步过程是“安全的”,那么您最终只会复制文件两次……这是一种浪费,但通常是无害的。
您可以通过使用这样的技术来缓解这种情况,以确保您的复制脚本一次不会运行多个。
这就是它的肉。您还可以使用组合(使用网络应用程序上传元数据,并使用通过 cron 自动运行的同步过程)。
您还可以有一个简单的网页,列出 /your/copy/dir 中的所有文件,以便人们可以查看他们的文件是否已同步。如果文件在此目录中,则它尚未完成同步。