设想:
我正在使用 SFTP 在两个系统 A 和 B 之间自动传输文件。
系统 A 运行 SFTP 服务器。系统 A 将定期(例如每分钟一次)轮询其本地 SFTP 目录是否存在 *.dat 文件,如果找到,则导入并删除它们。
系统 B 生成 *.dat 文件,并在生成后通过连接 SFTP 主机并上传将其发送到系统 A。
问题:
系统 A 有可能在系统 B 完成上传之前看到并开始处理文件吗?或者 SFTP 会以某种方式阻止这种情况,例如在网络传输完成之前不将文件存入文件夹?
系统 B 是否合理/建议使用其他文件名(例如 *.locked 或 *.part)上传,然后在网络传输完成后重命名为 *.dat?或者有更好的处理方法吗?
答案1
从定义上来说,这并非竞争条件,但是,系统 A 可能会打开部分上传的文件进行读取,因此包含无效数据。系统 A 可以检查文件的一致性,可以测试固定大小(如果合适),可以测试某些文件权限(上传后设置),并且在任何情况下,如果条件不满足,则推迟打开文件,在下一次迭代中打开。
我会将其上传到临时文件名或位置,然后重命名/移动到适合您程序的正确文件夹/扩展名。例如,上传到 filename.part,然后重命名为 filename.dat,或上传到未决/filename.dat,然后移出未决文件夹。这将解决任何此类问题。在 UNIX/Linux 和 Windows 系统上,移动操作(或重命名操作)将是原子的,您永远不会得到部分文件。
没有更好的方法来处理这个问题。您需要向系统 A 传达文件不完整且系统之间没有设置任何进程间通信。您的选择是使用锁定文件来阻止程序打开文件(稍后将其删除)、使用临时文件(然后将文件重命名/移动到适当的名称),或者进行某种完整性检查(这可能是一种资源浪费)。
您还可以考虑根据这种情况发生的频率,从系统 B 触发系统 A。如果 99% 的时间里都有文件,那么您已经提出的方法(带锁)可能是最有效的。另一方面,如果您只是偶尔找到数据,那么这可能是一种资源浪费(并且需要长时间运行或 cron 触发的程序)。如果您有 SFTP,您可能有 SSH 访问权限。在这种情况下,请在系统之间设置证书(为了避免需要密码,请参阅 ssh-copy-id)并运行一些修改版本的
ssh system_a.yourdomain.com'进程文件/home/user/data/*.dat'