динамично зададен upload_tmp_dir в apache2

Работя върху това с часове и това ме побърква!

така че мисля, че е наистина трудно, следователно подробният въпрос.

Проблемът е че:

  • Имам сървър, който приема качване на публикации на файлове чрез 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>

Това е само идея, все още не е тествана. все още се опитвам да го разбера. В този случай пътищата не са правилни, но може да има заобиколно решение със символни връзки. Ще бъде хубаво, ако някой може да ме насочи в правилната посока.


person The Surrican    schedule 18.04.2011    source източник
comment
Някаква причина да искате различни директории за качване? PHP вече присвоява произволно име на временния файл, така че е малко вероятно две или повече качвания да се стъпчат едно друго. Що се отнася до променливите на Apache, те се прилагат само в определени области, които конкретно ги търсят/очакват. php_value/php_admin_value не е един от тях.   -  person Marc B    schedule 19.04.2011
comment
в този случай различните директории са различни физически твърди дискове. Посочих причините във въпроса (без излишно копиране на файлове). всъщност качванията не са малко вероятни, но е невъзможно да се сблъскат с името им (ако приемем, че нямате споделено мрежово монтиране като временна директория за няколко сървъра или нещо подобно).   -  person The Surrican    schedule 19.04.2011
comment
Хванах те. Единственото нещо, за което мога да се сетя, е да задам vhost за всеки диск и да използвам правило за пренаписване, за да пренасоча качванията, когато влизат. След това можете да кодирате tmp пътя във всеки vhost, без да прибягвате до променливи. Освен ако не добавяте дискове с бясна скорост или имената им се променят често, може да е достатъчно, за да работи.   -  person Marc B    schedule 19.04.2011
comment
да, и аз мисля за това. проблемът е, че според настоящия ми дизайн местоположенията не са 1-n на всеки сървър, но всеки диск в целия облак има свой собствен идентификатор, следователно те могат да станат доста големи и ще трябва да конфигурирам vhosts за всеки сървър и ще трябва много поддръжка. надявах се да имам една обща конфигурация за всички сървъри, но подходът има смисъл, трябва да помисля още малко. може би мога да променя оформлението на моята база данни, за да диентифицирам дисковете по различен начин.   -  person The Surrican    schedule 19.04.2011
comment
защо е гласувано това да се изтрие? Виждам apache/php questinos през цялото време тук и мисля, че мястото им е тук. определено не мисля, че това трябва да бъде прехвърлено към уебмастърите. ако има някое място, тогава serverfault, но мисля, че принадлежи повече тук, отколкото на server fault, защото това определено е проблем на ниво приложение.   -  person The Surrican    schedule 19.04.2011
comment
Гласуването (не мое) е за просто затваряне извън темата, без миграция.   -  person Marc B    schedule 19.04.2011
comment
ако щракнете върху връзката за гласуване извън темата, виждате, че е хвърлено принадлежи към webmasters.stackexchange.com Въпроси и отговори за професионални уеб администратори   -  person The Surrican    schedule 19.04.2011
comment
За масов виртуален хостинг, погледнете mod_macro, ще можете да напишете всичките си VH с прости команди като Use MyVHOSt 42.somwhere.com dir42   -  person regilero    schedule 29.04.2011
comment
благодаря, трябва да проверя това +1 @regilero   -  person The Surrican    schedule 29.04.2011
comment
Направих някои тестове, комбинирайки mod_macro и LocationMatch или конкретни директиви за местоположение, но засега нямам успех, има много решения за променливи в конфигурацията, но не много за различни конфигурации...   -  person regilero    schedule 29.04.2011


Отговори (2)


Няма начин да използвате заместване на променливи в настройките на php_admin_value. Това е така, защото модулите на apache могат да анализират само своите собствени директиви за конфигурация. mod_rewrite поддържа използването на променливи на средата, защото това е вградено в самия mod_rewrite.

Тъй като не можете да използвате променливи, ще трябва да настроите всички възможни стойности, като използвате нещо като <Location>. Например:

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.

person Cal    schedule 03.05.2011
comment
добра идея е да използвате местоположение вместо vhosts! +1 по този начин мога да използвам същия домейн, което е удобно! идеята за скрипта b build също е добра, мисля, че ще го направя! има ли някаква конкретна причина, поради която не е възможно динамично? или е просто нещо, в което трябва да вярвам. може би би било възможно да се регистрира модул на apache? (определено бих предпочел вашето решение пред това, но просто от любопитство!) - person The Surrican; 03.05.2011
comment
просто защото модулите на apache могат да анализират само своите собствени директиви за конфигурация. mod_rewrite поддържа използването на променливи на средата, защото е вграден в mod_rewrite. алтернативата е да използвате mod_macro, което основно ви позволява да правите същото като по-горе, но с по-малък конфигурационен файл, генерирайки разширената конфигурация автоматично, но все още по същество просто генерирайки голям конфигурационен файл с много блокове vhost/локация. за да го направите толкова добре, колкото първоначално поискахте, трябва да модифицирате mod_php. - person Cal; 03.05.2011
comment
Благодаря! +1 бихте ли преместили този коментар нагоре в отговора си, така че да е пълен? - person The Surrican; 05.05.2011
comment
най-накрая промених малко вашето решение. вместо местоположение използвам locatin match, за да приложа регулярен израз. разделям обхватите си според сървърите. разпределих максимум 100 диска на сървър и използвах последните две цифри за идентифициране на диска. пр. 1001 е диск 01 на сървър 10. устройствата са монтирани съответно. по този начин съм добър със 100 правила за статично местоположение на всеки сървър. - person The Surrican; 28.05.2011
comment
тук също има дискусия относно основния проблем: old.nabble.com/LocationMatch -Regex-within--td13807271.html - person The Surrican; 28.05.2011

Ако съм разбрал правилно въпроса, винаги можете да използвате ini_set

ini_set ("upload_tmp_dir", "/home/thundercloud/locations/42/tmp"); 
person 0xAli    schedule 03.05.2011
comment
това не работи, защото трябва да зададете временната директория, преди заявката да бъде предадена от php. докато изпълнението премине към php, качените файлове вече са съхранени във временната директория - person Cal; 04.05.2011
comment
+1 това е правилната причина, но също така изрично е посочено в страниците за ръководство кои конфигурации са съвместими с ini set - person The Surrican; 05.05.2011