在apache2中动态设置upload_tmp_dir

发布于 2024-11-02 10:05:02 字数 3544 浏览 0 评论 0原文

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

所以我认为这是一个非常困难的问题,因此提出了详细的问题。

问题是:

  • 我有一个服务器接受通过 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"

所以显然这个“常量”在这个范围内不可用,

现在我已经没有想法了,

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

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

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

编辑:

好的,再过几个小时,Marc BI 的一个有用的评论提出了这个“解决方案”:

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

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

I am working on this for hours and its driving me nuts!

so i think its a really tough one hence the detailed question.

The problem is:

  • I have a server that accepts file post uploads by php script.

  • The data will be distributed to several discs.

  • I want to save the file to the right disc during upload (tmp file).

Because:

  • The file needs to be moved later, and i don't want it to take long (copy from the systems tmp directory to target disk)

  • The system drive is an ssd that won't be very happy when so much data is written and deleted on it.

This server config changes the init value. during an upload an can see the temp file and see how its filesize increases:

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

My sripts are in /home/thundercloud and there are several symlinks in /home/thundercloud/locations (named numerically 1-n) that all point to the according mountpoints.

Now what i need is to get the number 42 (which is disk no. 42 - no there are only 14 disks in the server, dis his just for test) to be dynamic.

I have a lot of control over the request so I basically don't care whether its determined by hostname, get variable, subdirectory etc.

So my first attempt was this:

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>

the corresponding rewrite map was:

#!/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;
}

I jut hardcoded 42. if it worked i would have parsed the correct falue from THE_REQUEST . It did not work. the script was chmod 777 and everything.

My next attempt was:

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>

no luck.

so my final attempt was:

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

no luck either. i printed ini_get_all() and got the following output:

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

so obviously this "constant" isn't available like this in this scope

now i ran out of ideas

i must admin my apporaches are really trial and error.

anyony can point me in the right direction or tell me its not possible and justify that?

ps: it obviously doesnt work at php runtime ;)

edit:

Ok after some more hours and a useful comment from Marc B I came up with this "solution":

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

Just brute force an own VirtualHost container for every disk... its ugly and I hoped to avoid that step and have a generic webserver config, but it seems like the only way to go - atleast it works.

I still wonder whether theres a nicer way and i think its very interesting to go so deep into webserver configurations. Apache is incredibly flexible and its getting really interesting when you push it to the limits (thats at least what i think).

Thats why I will leave this question open and put a bounty on it.

edit:

After some more research I think there might be a solution applying the techniques here:
http://httpd.apache.org/docs/2.0/vhosts/mass.html

something like:

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

This is just an idea, not tested yet. still trying to figure it out. The paths are not correct in this case but there might be a workaround with symlinks. Would be nice if some1 could point me in the right direction.

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

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

发布评论

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

评论(2

小巷里的女流氓 2024-11-09 10:05:02

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

由于您无法使用变量,因此您必须使用 之类的内容来设置所有可能的值。例如:

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 不适用于每个服务器,但无论如何都不会在那里发布任何内容。

另一种方法是使用 mod_macro,它基本上可以让您执行与上面相同的操作,但使用较小的配置文件,自动生成扩展配置,但本质上仍然只是生成一个包含大量虚拟主机/位置块的大配置文件。为了像您最初要求的那样好,您需要修改 mod_php。

There's no way to use variable substitution in php_admin_value settings. This is just because apache modules can only parse their own config directives. mod_rewrite supports using environment variables because doing so is built into mod_rewrite itself.

Because you can't use variables, you'll have to set up all of the possible values using something like <Location>'s. For example:

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>

Then you just post to /upload{$id}. This is obviously not as nicely dynamic as it would be if substitution were possible. There are 2 obvious alternatives to make it neater:

1) Have a separate build script which generates a file to put in /etc/httpd/conf.d with the relevant lines for each server

2) Create a universal config file which simply has e.g. the 100 location rules. On each server, you'd then just need to set up the symlinks you wanted and have the PHP which generates the form decide which volume to point the upload at - you'd end up with a bunch of /uploadX urls that wouldn't work on each server, but nothing would post there anyway.

The alternative is to use mod_macro, which basically lets you do the same as above but with a smaller config file, generating the expanded config automatically, but still essentially just generating a big config file with lots of vhost/location blocks. To do it as nicely as you original asked, you've need to modify mod_php.

疑心病 2024-11-09 10:05:02

如果我正确理解了这个问题,你总是可以使用 ini_set

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

If i understood the question correctly, you can always use ini_set

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