![以原子方式生成和复制文件的好策略是什么](https://linux22.com/image/55251/%E4%BB%A5%E5%8E%9F%E5%AD%90%E6%96%B9%E5%BC%8F%E7%94%9F%E6%88%90%E5%92%8C%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6%E7%9A%84%E5%A5%BD%E7%AD%96%E7%95%A5%E6%98%AF%E4%BB%80%E4%B9%88.png)
myfile
我有一个必须定期重新生成的文件。重新生成需要几秒钟。另一方面,我必须定期读取生成的最后一个(或倒数第二个)文件。保证我正在读取完全生成的文件并且一旦开始读取它就能够完全读取它的最佳方法是什么?
一种可能的解决方案是
myfile
实际上是到最后生成的文件的软链接,例如myfile.last
.- 再生是在一个新文件上完成的,比如说
myfile.new
- 再生后,
myfile.new
被移动到myfile.last
我看到的问题(我不知道答案)是:如果myfile
在 mv 发生时另一个脚本正在复制,是否cp
正确完成?
另一种可能的解决方案是生成名称上带有时间戳的文件,例如,myfile-2014-09-03_12:34
它又myfile
是指向最后创建的文件的软链接。创建后应更改此链接以指向新文件。再次:像这样的事情的可能性有多大
cp myfile anotherfile
复制损坏的文件?
答案1
如果您在同一个文件系统中移动,则mv
这是原子的——这只是重命名,而不是复制内容。因此,如果你们这一代人的最后一步是:
mv myfile.new myfile.last
读取过程将始终看到文件的旧版本或新版本,永远不会出现任何不完整的内容。
答案2
您可以简化您的第一个建议的解决方案:将文件重新生成为myfile.new
,然后将mv
其重命名 ( ) 为myfile
。
如果你是覆盖 myfile
对于新数据,异步读取器可能会获取损坏(或至少不完整)的数据 - 但您已经知道了。我非常确定您提出的任何一个解决方案都是安全的。如果另一个进程在 12:38 打开该文件的 12:34 版本,那么它将继续拥有那个文件将 12:39 版本的文件重命名为 后打开进行阅读myfile
,即使它不再出现在任何目录中。在第二种情况下,这一点更加明确,在您将符号链接更改为指向 12:39 文件后,12:34 版本仍保留在目录中。