12

我一直在 CentOS 6 上使用 Capistrano 设置 PHP 部署,并遇到了一个有趣的问题。capistrano 的工作方式是这样设置文件夹:

  • /var/www/myapp.com/
    • 当前(/releases 中最新版本的符号链接)
    • 共享
    • 发布
      • 20130826172737
      • 20130826172114

当我查看“当前”符号链接时,它指向最新版本。起初,打开我的网络应用程序时,一切正常。部署新版本后,当前文件夹正确指向新版本,但 Web 应用程序尝试从旧版本加载文件(已在 Capistrano 清理过程中删除)。此外,虚拟主机配置为指向/var/www/myapp.com/current/Public

符号链接是否以任何方式缓存?

失败的特定 PHP 代码(初始化我的框架)是这样的:

require_once dirname(dirname(__FILE__)) . '/App/App.php';
App\App::run();

那是在index.php当前位于/var/www/app.com/current/Public/index.php

我的 Apache 错误日志显示:

PHP致命错误:require_once():打开失败需要'/var/www/myapp.com/releases/20130826172237/App/App.php'(include_path ='。:/usr/share/pear:/usr/share/php ') 在 /var/www/myapp.com/releases/20130826172237/Public/index.php

当前的符号链接显示:

当前-> /var/www/zverse/releases/20130826172641

显然 20130826172641 != 20130826172237 后者是以前的版本。

我可以看看任何想法或领域吗?

4

2 回答 2

4

您是否检查了 realpath_cache_size 和 realpath_cache_ttl 指令?默认情况下,php > 5.1 会将符号链接文件的真实路径缓存 120 秒。这将导致 capistrano 部署出现问题。主要问题是缓存——即使你清除了缓存,你的旧 php 文件将继续提供两分钟,用旧数据重新填充它——以及 php 和静态文件之间的交互。静态文件由 Apache 直接提供,因此会立即更新。不过,在部署后两分钟内,php 代码仍将来自先前版本,因此它将期待任何更改的静态文件的旧版本。如果您使用更改这些文件名称的缓存中断过程,这尤其是一个问题。在那种情况下,php代码将无法找到它的文件'

无论如何,有两种解决方案。首先是在 php.ini 中将 realpath_cache_size 设置为 0。(注意:将 realpath_cache_ttl 设置为 0 不会禁用缓存。)或者,如果您想保持启用状态,您应该能够使用clearstatcache函数在部署符号链接后立即使用 capistrano 挂钩清除 realpath 缓存。但是请注意,如果您使用的是 mod_php,则 php cli 和 apache 运行时是分开的,因此您需要使用 apache 调用的 php 脚本调用该函数,类似于在此处清除 APC 缓存所做的操作。不过我还没有测试过,因为我没有注意到简单地禁用缓存会对性能产生重大影响。

于 2014-05-02T02:43:59.113 回答
4

我无法验证这一点,但似乎 Apache 跟随/缓存符号链接的旧位置有一些不可预测的行为:

唯一能彻底解决这个问题的是循环 Apache,我们不希望在每次部署时都这样做。——迈克·布里顿

他建议移动整个目录,而不是更新符号链接。

于 2013-10-28T08:40:54.633 回答