【问题标题】:dynamically set upload_tmp_dir in apache2在apache2中动态设置upload_tmp_dir
【发布时间】:2011-08-08 04:10:46
【问题描述】:

我为此工作了好几个小时,这让我发疯了!

所以我认为这是一个非常棘手的问题,因此需要详细的问题。

问题是:

  • 我有一个服务器,可以接受通过 php 脚本上传的文件。

  • 数据将分布到多张光盘上。

  • 我想在上传过程中将文件保存到正确的光盘(tmp 文件)。

因为:

  • 文件需要稍后移动,我不希望它花费很长时间(从系统 tmp 目录复制到目标磁盘)

  • 系统盘是一个ssd,在上面写入和删除这么多数据时不会很开心。

此服务器配置更改了初始值。在上传过程中,可以看到临时文件并查看其文件大小如何增加:

Alias /thundercloud /home/thundercloud
<Directory /home/thundercloud>
    php_admin_value upload_tmp_dir /home/thundercloud/locations/42/tmp
</Directory>

我的脚本在 /home/thundercloud 中,并且在 /home/thundercloud/locations 中有几个符号链接(以数字 1-n 命名)都指向相应的挂载点。

现在我需要让数字 42(即磁盘号 42 - 不,服务器中只有 14 个磁盘,这只是为了测试)是动态的。

我对请求有很多控制权,所以我基本上不在乎它是否由主机名、获取变量、子目录等决定。

所以我的第一次尝试是这样的:

RewriteLock /var/lock/apache2/rewrite.lock
Alias /thundercloud /home/thundercloud
RewriteMap getuplaodlocation prg:/home/thundercloud/uploadloc.php
RewriteEngine On
<Directory /home/thundercloud>
    AllowOverride All
    php_admin_value upload_tmp_dir ${getuplaodlocation:%{THE_REQUEST}}
</Directory>

对应的重写映射为:

#!/usr/bin/php
<?
set_time_limit(0); # forever program!
$keyboard = fopen("php://stdin","r");
while (1) {
    $line = trim(fgets($keyboard)); // dont care for now
    echo '/home/thundercloud/locations/42/tmp'.PHP_EOL;
}

我只是硬编码 42。如果它有效,我会从 THE_REQUEST 解析正确的值。它不起作用。脚本是 chmod 777 和所有内容。

我的下一个尝试是:

Alias /thundercloud /home/thundercloud
<Directory /home/thundercloud>
    SetEnvIfNoCase Host lionel\.2x\.to upload=/home/thundercloud/locations/42/tmp
    php_admin_value upload_tmp_dir upload
</Directory>

运气不好。

所以我最后的尝试是:

Alias /thundercloud /home/thundercloud
<Directory /home/thundercloud>
    php_admin_value upload_tmp_dir /home/thundercloud/locations/%{REMOTE_HOST}/tmp
</Directory>

也没有运气。我打印了 ini_get_all() 并得到以下输出:

["upload_tmp_dir"]=>
  array(3) {
    ["global_value"]=>
    string(47) "/home/thundercloud/locations/%{REMOTE_HOST}/tmp"

所以很明显这个“常数”在这个范围内是不可用的

现在我的想法已经用完了

我必须管理我的方法确实是反复试验。

任何人都可以指出正确的方向或告诉我这是不可能的并证明这一点?

ps:它显然在 php 运行时不起作用;)

编辑:

好吧,经过几个小时和 Marc B 的有用评论后,我想出了这个“解决方案”:

<VirtualHost *:80>
    ServerName 42.thundercloud.lionel.2x.to
    DocumentRoot /home/thundercloud
    php_admin_value upload_tmp_dir /home/thundercloud/locations/42/tmp
</VirtualHost>
<VirtualHost *:80>
    ServerName 43.thundercloud.lionel.2x.to
    DocumentRoot /home/thundercloud
    php_admin_value upload_tmp_dir /home/thundercloud/locations/43/tmp
</VirtualHost>

只需为每个磁盘强制使用一个自己的 VirtualHost 容器...它很丑陋,我希望避免这一步并拥有一个通用的网络服务器配置,但它似乎是唯一的方法 - 至少它可以工作。

我仍然想知道是否有更好的方法,我认为深入研究网络服务器配置非常有趣。 Apache 非常灵活,当你把它推到极限时它会变得非常有趣(至少我是这么认为的)。

这就是为什么我会留下这个问题并悬赏它。

编辑:

经过更多研究,我认为可能有一个解决方案在此处应用这些技术: http://httpd.apache.org/docs/2.0/vhosts/mass.html

类似:

<VirtualHost *> 
Use CanonicalName off
VirtualDocumentRoot /home/thundercloud/locations/%0/tmp/
php_admin_value open_basedir VIRTUAL_DOCUMENT_ROOT
<VirtualHost>

这只是一个想法,尚未测试。仍在试图弄清楚。在这种情况下,路径不正确,但可能有符号链接的解决方法。如果 some1 可以为我指明正确的方向,那就太好了。

【问题讨论】:

  • 你想要不同的上传目录有什么理由吗? PHP 已经为临时文件分配了一个随机名称,因此两个或多个上传不太可能相互踩踏。至于 Apache 变量,这些变量仅适用于专门寻找/期望它们的某些领域。 php_value/php_admin_value 不是其中之一。
  • 在这种情况下,不同的目录是不同的物理硬盘。我在问题中说明了原因(没有多余的文件复制)。事实上,上传不是不太可能,但不可能通过他们的名字来收集(假设你没有一个共享的网络挂载作为多个服务器的临时目录或其他东西)。
  • 明白了。我唯一能想到的就是为每个磁盘设置一个虚拟主机,并使用重写规则在上传时重新路由上传。然后您可以在每个虚拟主机中硬编码 tmp 路径,而无需使用变量。除非您以极快的​​速度添加磁盘或者它们的名称经常更改,否则它可能就足够了。
  • 是的,我也在考虑这个问题。问题是根据我目前的设计,每个服务器上的位置不是 1-n,而是整个云中的每个磁盘都有自己的 id,因此它们可以变得非常大,我必须为每台服务器配置虚拟主机,它需要很多维护。我希望为所有服务器提供一个通用配置,但方法是有道理的,需要多考虑一下。也许我可以改变我的数据库布局来区分磁盘。
  • 对于大规模虚拟主机,请查看 mod_macro,您将能够使用“使用 MyVHOSt 42.somwhere.com dir42”等简单命令编写所有 VH

标签: php apache .htaccess configuration initialization


【解决方案1】:

无法在php_admin_value 设置中使用变量替换。这只是因为 apache 模块只能解析它们自己的配置指令。 mod_rewrite 支持使用环境变量,因为这样做是内置于 mod_rewrite 本身的。

因为您不能使用变量,所以您必须使用类似&lt;Location&gt;'s 的方式设置所有可能的值。例如:

RewriteEngine on
RewriteRule /upload(\d+)$       /upload.php

php_admin_value upload_tmp_dir /tmp

<Location /upload1>
    php_admin_value upload_tmp_dir /tmp/1
</Location>
<Location /upload2>
    php_admin_value upload_tmp_dir /tmp/2
</Location>
....
<Location /upload100>
    php_admin_value upload_tmp_dir /tmp/100
</Location>

然后你只需发帖到/upload{$id}。这显然不像可以替代的情况那样动态化。有 2 种明显的替代方法可以使它更整洁:

1) 有一个单独的构建脚本,它会生成一个文件以放入 /etc/httpd/conf.d 中,其中包含每个服务器的相关行

2) 创建一个通用配置文件,其中包含例如100 个位置规则。在每台服务器上,您只需要设置您想要的符号链接,并让生成表单的 PHP 决定将上传指向哪个卷 - 您最终会得到一堆 /uploadX url t 在每台服务器上都可以工作,但无论如何都不会在那里发布任何内容。

另一种方法是使用 mod_macro,它基本上可以让您执行与上述相同的操作,但使用较小的配置文件,自动生成扩展配置,但本质上仍然只是生成一个包含大量 vhost/location 块的大配置文件。要按照您最初的要求做到这一点,您需要修改 mod_php。

【讨论】:

  • 使用位置而不是虚拟主机的好主意! +1 这样我就可以使用相同的域,这很方便!构建脚本的想法也很好,我想我会这样做!是否有任何具体原因无法动态实现?或者这只是我必须相信的事情。也许可以使用 apache 模块? (我肯定会更喜欢你的解决方案,但只是出于好奇!)
  • 只是因为 apache 模块只能解析自己的配置指令。 mod_rewrite 支持使用环境变量,因为它内置于 mod_rewrite。另一种方法是使用 mod_macro,它基本上可以让您执行与上述相同的操作,但使用较小的配置文件,自动生成扩展配置,但本质上仍然只是生成一个包含大量 vhost/location 块的大配置文件。要按照您最初的要求做到这一点,您需要修改 mod_php。
  • 谢谢! +1 您会将评论移到您的答案中以使其完整吗?
  • 我终于稍微调整了您的解决方案。而不是位置,我使用 locatin 匹配来应用正则表达式。我根据服务器划分我的范围。我为每台服务器分配了最多 100 个磁盘,并使用最后两位数字来标识磁盘。前任。 1001 是服务器 10 上的磁盘 01。相应地安装了驱动器。这样我就可以在每个服务器上使用 100 个静态位置规则。
  • 这里还有一个关于核心问题的讨论:old.nabble.com/LocationMatch-Regex-within--td13807271.html
【解决方案2】:

如果我对问题的理解正确,您可以随时使用 ini_set

ini_set ("upload_tmp_dir", "/home/thundercloud/locations/42/tmp"); 

【讨论】:

  • 这不起作用,因为您必须在请求被移交给 php.ini 之前设置临时目录。当执行传递给 php 时,上传的文件已经存储在 temp dir 中
  • +1 这是正确的原因,但它也在手册页中明确说明了哪些配置与 ini 集兼容
猜你喜欢
  • 2014-05-14
  • 2019-10-28
  • 2014-05-05
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 2018-04-29
相关资源
最近更新 更多