динамически устанавливает upload_tmp_dir в apache2

#php #apache #.htaccess #configuration #initialization

#php #apache #.htaccess #конфигурация #инициализация

Вопрос:

Я работаю над этим часами, и это сводит меня с ума!

итак, я думаю, что это действительно сложный вопрос, отсюда и подробный вопрос.

Проблема в том:

  • У меня есть сервер, который принимает почтовые загрузки файлов с помощью php-скрипта.

  • Данные будут распределены на несколько дисков.

  • Я хочу сохранить файл на нужный диск во время загрузки (файл tmp).

Потому что:

  • Файл необходимо переместить позже, и я не хочу, чтобы это занимало много времени (скопируйте из системного каталога tmp на целевой диск)

  • Системный диск — это твердотельный накопитель, который не будет очень доволен, когда на него будет записано и удалено так много данных.

Эта конфигурация сервера изменяет значение init. во время загрузки можно просмотреть временный файл и увидеть, как увеличивается его размер:

 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 дисков, это его просто для теста) динамичным.

У меня есть большой контроль над запросом, поэтому мне в принципе все равно, определяется ли он именем хоста, переменной get, подкаталогом и т.д.

Итак, моя первая попытка была такой:

 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. если бы это сработало, я бы проанализировал правильный falue из 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>
  

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

теперь у меня закончились идеи

я должен администрировать мои приложения, которые действительно выполняются методом проб и ошибок.

кто-нибудь может указать мне правильное направление или сказать, что это невозможно, и обосновать это?

ps: очевидно, что это не работает во время выполнения php 😉

Редактировать:

Хорошо, еще через несколько часов и полезный комментарий от Марка Б. я придумал это «решение»:

 <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 мог указать мне правильное направление.

Комментарии:

1. По какой-либо причине вы хотите разные каталоги для загрузки? PHP уже присваивает временному файлу случайное имя, поэтому две или более загрузки вряд ли будут мешать друг другу. Что касается переменных Apache, они применяются только в определенных областях, которые специально ищут / ожидают их. php_value / php_admin_value не является одним из них.

2. в этом случае разные каталоги являются разными физическими жесткими дисками. я изложил причины в вопросе (без избыточного копирования файлов). на самом деле загрузки не маловероятны, но их невозможно определить по их имени (при условии, что у вас нет общего сетевого подключения в качестве временного каталога для нескольких серверов или чего-то еще).

3. Понял. Единственное, что я могу придумать, это установить виртуальный хост для каждого диска и использовать правило перезаписи для изменения маршрута загрузок по мере их поступления. Затем вы можете жестко закодировать путь tmp в каждом виртуальном хостинге, не прибегая к переменным. Если вы не добавляете диски с бешеной скоростью или их имена часто меняются, этого может быть достаточно для работы.

4. да, я тоже об этом думаю. проблема в том, что по моему текущему дизайну местоположения не равны 1-n на каждом сервере, но каждый диск во всем облаке имеет свой собственный идентификатор, поэтому они могут стать довольно большими, и мне пришлось бы настраивать vhosts для каждого сервера, и это потребовало бы большого обслуживания. я надеялся иметь одну общую конфигурацию для всех серверов, но оценка имеет смысл, нужно еще немного подумать. возможно, я могу изменить макет своей базы данных, чтобы различать диски по-другому.

5. Для массового виртуального хостинга, взгляните на mod_macro, вы сможете записать весь свой виртуальный файл с помощью простых команд, таких как «Использовать MyVHOSt 42.somwhere.com dir42»

Ответ №1:

В php_admin_value настройках невозможно использовать замену переменных. Это просто потому, что модули apache могут анализировать только свои собственные директивы конфигурации. mod_rewrite поддерживает использование переменных окружения, поскольку это встроено в сам mod_rewrite.

Поскольку вы не можете использовать переменные, вам придется настроить все возможные значения, используя что-то вроде <Location> ‘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-адресов, которые не будут работать на каждом сервере, но там все равно ничего не будет размещаться.

Альтернативой является использование mod_macro, который в основном позволяет вам делать то же самое, что и выше, но с файлом конфигурации меньшего размера, автоматически генерируя расширенную конфигурацию, но по сути просто генерируя большой файл конфигурации с большим количеством блоков vhost / location. Чтобы сделать это так красиво, как вы изначально просили, вам нужно изменить mod_php.

Комментарии:

1. хорошая идея использовать location вместо vhosts! 1 таким образом, я могу использовать тот же домен, что и удобно! идея скрипта b uild тоже хороша, я думаю, что я собираюсь это сделать! есть ли какая-либо конкретная причина, по которой это невозможно динамически? или это просто то, во что я должен верить. возможно, было бы возможно usign модуль apache? (я бы определенно предпочел ваше решение этому, но просто из любопытства!)

2. это просто потому, что модули apache могут анализировать только свои собственные директивы конфигурации. mod_rewrite поддерживает использование переменных окружения, потому что это встроено в mod_rewrite. альтернативой является использование mod_macro, который в основном позволяет вам делать то же самое, что и выше, но с файлом конфигурации меньшего размера, автоматически генерируя расширенную конфигурацию, но по сути просто генерируя большой файл конфигурации с большим количеством блоков vhost / location. чтобы сделать это так красиво, как вы изначально просили, вам нужно изменить mod_php.

3. Спасибо! 1 не могли бы вы переместить этот комментарий в свой ответ, чтобы он был полным?

4. я, наконец, немного изменил ваше решение. вместо location я использую locatin match для применения регулярного выражения. я разделяю свои диапазоны в соответствии с серверами. я выделил максимум 100 дисков на сервер и использую последние две цифры для идентификации диска. например. 1001 — это диск 01 на сервере 10. диски смонтированы соответствующим образом. таким образом, я согласен со 100 статическими правилами размещения на каждом сервере.

5. здесь также обсуждается основная проблема: old.nabble.com/LocationMatch-Regex-within—td13807271.html

Ответ №2:

Если я правильно понял вопрос, вы всегда можете использовать ini_set

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

Комментарии:

1. это не работает, потому что вы должны установить временный каталог, прежде чем запрос будет передан с php. к тому времени, когда выполнение переходит на php, загруженные файлы уже были сохранены во временном каталоге

2. 1 это правильная причина, но также явно указано на страницах руководства, какие конфигурации совместимы с набором ini