替换服务器上文件的最佳方法

发布于 2024-09-25 13:47:07 字数 513 浏览 0 评论 0原文

我必须用 PHP 编写脚本,该脚本将不时动态替换服务器上的某些文件。很简单,但问题是我想避免用户在替换期间请求此文件的情况。然后他可能会得到未完成的文件甚至错误。

对我来说最好的解决方案是在替换过程中阻止对我的网站的访问,例如设置 .htaccess 将所有请求重定向到包含短暂休息信息的页面。但通常.htaccess文件已经存在,因此可能会出现服务器获取未完成的.htaccess文件的情况。

有什么办法可以解决吗?

编辑:非常感谢你们的所有回答,伙计们。你很聪明。

@ircmaxell 你的想法对我来说听起来很棒。我读了 PHP.net 的家伙写的内容,但我不知道我是否理解正确。

那么,告诉我:如果我执行您编写的所有步骤并将 apc.file_update_protection 添加到我的 php.ini 中,则用户将无法随时获取未完成的文件?总会有一个正确的文件?你确定100%吗?

这对我来说非常重要,因为这些替换会非常频繁,并且在重命名期间有很大的机会请求文件。

I have to write script in PHP which will be dynamicly replace some files on server from time to time. Easy thing, but the problem is that I want to avoid situation when user request this file during replacing. Then he could get uncompleted file or even error.

Best solution to me is block access to my site during replacing by e.g. setting .htaccess redirecting all requests to page with information about short break. But normally .htaccess file already exist, so there may be situation when server gets uncomplited .htaccess file.

Is there any way to solve it?

Edit: Thank you so much for all answers, guys. You are briliant.

@ircmaxell Your idea sounds great for me. I read what dudes from PHP.net wrote and I don't know if I understand all correctly.

So, tell me: If I do all steps you wrote and add apc.file_update_protection to my php.ini, there will be no way to get uncompleted file by user by any time? There will be always one, correct file? Are you sure at 100% ?

It is very important to me coz these replacements will be very often and there is big chance to request file during renaming.

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

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

发布评论

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

评论(5

昇り龍 2024-10-02 13:47:07

下面的操作很简单,并且适用于 Linux 上的任何本地文件系统:

  1. 将文件上传(或写入)到临时文件名
  2. 移动文件(使用 mv(移动)命令,无论是在 FTP 中,还是命令行等,或重命名 PHP 中的命令)来覆盖现有的。

当您执行 mv 命令时,它基本上会删除旧的文件指针,并写入新的文件指针。由于它是在文件系统级别完成的,因此它是一个原子操作。因此客户端无法获取旧文件...

APC 建议 这样做是为了防止这些问题突然出现...

另请注意,您也可以使用 rsync 来执行此操作(因为它基本上在幕后执行此操作)...

Here's something that's easy, and will work on any local filesystem on linux:

  1. Upload (or write) the file to a temporary filename
  2. Move the file (using the mv (move) command, either in FTP, or command line, etc, or the rename command in PHP) to overwrite the existing one.

When you execute the mv command, it basically deletes the old file pointer, and writes the new one. Since it's being done at the filesystem level, it's an atomic operation. So the client can't get an old file...

APC recommends doing this to prevent these very issues from cropping up...

Also note that you could use rsync to do it as well (since it basically does this behind the scenes)...

一杆小烟枪 2024-10-02 13:47:07

这还不行吗?我从未专门对此进行过测试,但我已经完成了您正在做的事情,并且该问题从未出现。
对于操作系统来说,

  1. 上传/写入临时文件
  2. 似乎是一件容易的事情。写入完成后,阻止对原始文件的访问(使文件请求等待)
  3. 删除文件,重命名临时文件并删除所有锁定

我相当确定这就是操作系统应该执行的复制操作。如果您自己使用 PHP 编写文件内容,您只需自己执行此操作...

Doesn't this work already? I never tested for this specifically but I've done what you're doing and that problem never showed up.
It seems like an easy thing for an operating system to

  1. Upload / write to a temporary file
  2. When writing is done, block access to the original file (make the request for the file wait)
  3. Delete the file, rename the temporary one and remove any locks

I'm fairly sure this is what an OS should do for copying. If you're writing the file contents yourself with PHP you'll just have to do this yourself...

浪菊怪哟 2024-10-02 13:47:07

尝试railless Capistrano 或他们使用的方法:

在目录中你有两个东西:

  1. 一个包含文件夹的文件夹,每个子文件夹都是一个release
  2. 当前release文件夹的软链接

当您上传新文件时,上传会创建一个新的release文件夹。检查当前是否没有人在运行当前版本(假设您没有大量用户,您可能可以使用数据库条目来完成此操作,这可能有点棘手),然后重写软链接以指向最新版本。

Try railless Capistrano or a method they use:

in a directory you have two things:

  1. A folder containering folders, each subfolder is a release
  2. A soft link to the current release folder

When you upload the new file, do the upload making a new release folder. Check to see that no one is currently running the current release (this might be a little tricky assuming you dont have a crazy number of users you could probably do it with a db entry) and then rewrite the softlink to point to the newest release.

纵情客 2024-10-02 13:47:07

也许可以这样尝试:

  1. 删除文件并保存它的路径
  2. ln -nfs movingfilepath pathtosorrypage.html
  3. 将文件上传到服务器上的某个临时文件夹
  4. 删除符号链接
  5. mv newfile movingfilepath

maybe do try it like this:

  1. delete file and save it's path
  2. ln -nfs movedfilepath pathtosorrypage.html
  3. upload file to some temporary folder on the server
  4. remove symlink
  5. mv newfile movedfilepath
过度放纵 2024-10-02 13:47:07

方案一:如果你有很多用户,而且这种更换不那么频繁,你可以在网站上设置一个维护(阻止访问),并在一段时间后没有人登录,最后切断所有正在访问的人。当您要进行更换时,请先登录。

选项2:如果文件替换经常进行(在这种情况下您不应该每天进行维护),请通过代码完成。有两个相同的文件(如果需要,可以在同一文件夹中)。然后,通过代码,当您要替换文件时,让它只提供副本,同时替换您想要的文件。你可以用一个简单的 IF 来完成。

伪代码:

if (replaceTime - 15 seconds <= currentTime <= replaceTime + 15 seconds){
    // allows 30 seconds for another script to bring in the new image into 'myImage.jpg'
    <img src="/myFiles/myOldImage.jpg" />
} else {
    <img src="/myFiles/myImage.jpg" />
}

无需更新任何数据库或手动移动/复制/重命名文件。

replaceTime + 15过去后:

copyFileTo("myImage.jpg","myOldImage.jpg");
// Now you have the copy ready for the next time to replace

Option 1: If you have a lot of users and this replacing is done not so frequent, you can set up a maintenance on the site (block access) and have no one log in after a certain time, and finally cut off everyone who is logged in when you're about to do the replacement.

Option 2: If the file replacing is done frequently (in which case you shouldn't do the maintenance every day), have it done by code. Have two of the same files (same folder if you want). Then, by code, when you're about to replace the file, have it just give the copy, while you replace the one you want. You can do it with a simple IF.

Pseudo-code:

if (replaceTime - 15 seconds <= currentTime <= replaceTime + 15 seconds){
    // allows 30 seconds for another script to bring in the new image into 'myImage.jpg'
    <img src="/myFiles/myOldImage.jpg" />
} else {
    <img src="/myFiles/myImage.jpg" />
}

No need to update any database or manually move/copy/rename a file.

After replaceTime + 15 has passed:

copyFileTo("myImage.jpg","myOldImage.jpg");
// Now you have the copy ready for the next time to replace
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文