原子创建文件的最佳方法

发布于 2024-08-02 12:41:18 字数 402 浏览 2 评论 0原文

以原子方式创建新文件的“最佳实践”(据我所知)是打开一个临时文件(使用 tmpfile()),然后将文件移动到其最终位置。

但是,如果临时文件位于不同的安装点上,这将无法正常工作,因为这将导致文件逐渐累积,并额外导致不必要的 IO 开销。

另一种选择是在与最终目标相同的目录中创建一个临时文件,但这具有为用户创建不寻常文件的缺点(MS Word 和 ViM 等应用程序会这样做,但我也认为这种行为不好)。

是否有与 tmpfile() 类似的方法允许我指定挂载点?我意识到这可能不存在于 PHP 中,因此 Posix/C 函数或 shell 调用也是可以接受的。

The 'best practice' (as I see it) to atomically create a new file, is to open a temporary file (using tmpfile()), and then moving the file to it's final location.

However, this won't work well if the temporary file is on a different mountpoint, as this will result in the file gradually building up and additionally result in unneeded IO overhead.

Another option is to create a temporary file in the same directory as the final destination, but this has the disadvantage of creating a unusual file for a user (Apps such as MS Word and ViM do this, but I also consider this bad behaviour).

Is there a similar method as tmpfile() that will allow me to specify the mountpoint? I realize this probably doesn't exist built-into PHP, so a Posix/C-function or shell-call is also acceptable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遇见了你 2024-08-09 12:41:18

不,POSIX 堆栈中没有这样的方法。 tmpfile() 和 tmpname() 用于普通临时目录。有 tempnam(),您可以在其中指定目标目录对于临时文件。但这基本上是实现您描述的第二个选项的一种方法。

No, there isn't such a method in the POSIX stack. tmpfile() and tmpname() use to normal temp dir. There is the tempnam(), where you can specific the target directory for the temp file. But is is basically a way to implement the second option you described.

合约呢 2024-08-09 12:41:18

qmail 开发的 maildir 协议为多个写入者到同一目标目录,甚至跨 NFS。在此方案中,保证“tempfile”目录与目标目录位于同一文件系统上。

该算法可以在高效的 shell 实用程序 safecat,其联机帮助页将算法描述为:

safecat 通过六个步骤写入数据来应用 maildir 算法。
首先,它 stat()s 两个目录 tempdir 和 destdir,然后退出
除非两个目录都存在并且可写。其次,它 stat() 是
名称 tempdir/time.pid.host,其中 time 是自开始以来的秒数
1970 GMT 年初,pid 是程序的进程 ID,host 是
主机名。第三,如果 stat() 返回 ENOENT 以外的任何内容,
程序休眠两秒,更新时间,并尝试 stat()
再次强调,次数有限。四、程序创建
临时目录/time.pid.host。五、程序NFS——将消息写入
文件。第六,程序将文件链接到 destdir/time.pid.host。在
那一刻数据已成功写入。

此外,safecat 在创建之前会启动一个 24 小时计时器
tempdir/time.pid.host,如果计时器到期则中止写入。之上
错误、超时或正常完成,safecat 尝试 unlink()
tempdir/time.pid.host。

The maildir protocol developed for qmail provides safe file creation for multiple writers to the same target directory, even across NFS. In this scheme, the "tempfile" directory is guaranteed to be on the same filesystem as the target dir.

The algorithm is conveniently implemented in an efficient shell utility, safecat, whose manpage presents the algorithm as:

safecat applies the maildir algorithm by writing data in six steps.
First, it stat()s the two directories tempdir and destdir, and exits
unless both directories exist and are writable. Second, it stat()s the
name tempdir/time.pid.host, where time is the number of seconds since
the beginning of 1970 GMT, pid is the program's process ID, and host is
the host name. Third, if stat() returned anything other than ENOENT,
the program sleeps for two seconds, updates time, and tries the stat()
again, a limited number of times. Fourth, the program creates
tempdir/time.pid.host. Fifth, the program NFS-writes the message to the
file. Sixth, the program link()s the file to destdir/time.pid.host. At
that instant the data has been successfully written.

In addition, safecat starts a 24-hour timer before creat-ing
tempdir/time.pid.host, and aborts the write if the timer expires. Upon
error, timeout, or normal completion, safecat attempts to unlink()
tempdir/time.pid.host.

故事未完 2024-08-09 12:41:18

当您谈论“挂载点”时,我假设您处于类 UNIX 环境中。

也许您可以将其视为一种解决方法或不良行为,但我认为在同一目标文件夹上创建隐藏(.tmpfile)临时文件是可以接受的。

当然,如果您不想在目标目录中看到任何虚假文件,您当然可以在适合此任务的应用程序无法访问的同一安装点上创建一个特定文件夹,以这种方式在同一安装点上模拟 tempfile() 。

As you are talking about the "mountpoint" I'm assuming you are on a unix-like environment.

Maybe you can consider it a workaround or bad-behavior, but I think creating an hidden (.tmpfile) temp file on the same destination folder could be acceptable.

You can of course create a specific folder on the same mount point not accessible to the application suited for this task, simulating this way a tempfile() on the same mountpoint, if you don't want to see any spurious file in the destination dir.

蓝礼 2024-08-09 12:41:18

我必须做这样的事情并使用 MySQL 数据库。只是将我需要的信息存储在表中,完成后我删除了该记录。只是一个想法:)

I had to do something like this and went with a MySQL DB. Just stored the info I needed in a table and when I was finished I just deleted the record. Just a thought :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文