【问题标题】:Best way to replace file on server替换服务器上文件的最佳方法
【发布时间】:2010-10-01 14:19:42
【问题描述】:

我必须用 PHP 编写脚本,它会不时动态地替换服务器上的一些文件。简单的事情,但问题是我想避免用户在替换过程中请求这个文件的情况。然后他可能会得到未完成的文件甚至错误。

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

有什么办法可以解决吗?

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

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

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

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

【问题讨论】:

    标签: php .htaccess deployment


    【解决方案1】:

    这里有一些简单的东西,可以在 linux 上的任何本地文件系统上运行:

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

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

    APC 推荐doing this 以防止这些问题突然出现...

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

    【讨论】:

      【解决方案2】:

      这不是已经奏效了吗?我从来没有专门测试过这个,但我已经做了你正在做的事情,这个问题从未出现过。 对于操作系统来说,这似乎是一件容易的事

      1. 上传/写入临时文件
      2. 写入完成后,阻止对原始文件的访问(等待文件请求)
      3. 删除文件,重命名临时文件并移除所有锁

      我很确定这是操作系统在复制时应该做的事情。如果您使用 PHP 自己编写文件内容,您只需要自己执行此操作...

      【讨论】:

        【解决方案3】:

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

        在一个目录中你有两个东西:

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

        当您上传新文件时,请上传新的发布文件夹。检查以查看当前没有人在运行当前版本(这可能有点棘手,假设您没有大量用户,您可能可以使用 db 条目来执行此操作),然后重写软链接以指向最新版本。

        【讨论】:

          【解决方案4】:

          也许可以这样尝试:

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

          【讨论】:

            【解决方案5】:

            方案一:如果你有很多用户,而且这个替换不是那么频繁,你可以在网站上设置一个维护(阻止访问),并且在一定时间之后没有人登录,最后切断在您即将进行替换时登录的每个人。

            选项 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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-02-19
              • 2014-04-30
              • 1970-01-01
              • 2019-05-29
              • 1970-01-01
              • 2011-01-14
              • 2017-08-23
              相关资源
              最近更新 更多