Использование переменных в конфигурационных файлах Apache для уменьшения дублирования?


67

Можно ли использовать переменные в конфигурационных файлах Apache?

Например, когда я настраиваю сайт с помощью Django + WSGI, файл конфигурации может выглядеть следующим образом:

<Directory /path/to/foo/>
    Order allow,deny
    Allow from all
</Directory>
Alias /foo/static /path/to/foo/static
WSGIScriptAlias /foo /path/to/foo/run_wsgi

И я хотел бы превратить / path / to / foo в переменную, чтобы ее можно было определить только в одном месте. Что-то вроде:

Variable FOO /path/to/foo
…

Спасибо!

Ответы:


66

Вы можете использовать mod_macro , который был включен в Apache httpd с версии 2.4

Перед этим его нужно было установить отдельно, см. Mod_macro . Например , на Debian: apt-get install libapache2-mod-macro; a2enmod macro.

Пример конфигурации

/etc/apache2/conf.d/vhost.macro

<Macro VHost $host $port>
  <VirtualHost $host:$port>

    ServerName $host
    DocumentRoot /var/vhosts/$host

    <Directory /var/vhosts/$host>
      # do something here...
    </Directory>
  </VirtualHost>
</Macro>

/etc/apache2/sites-available/vhost.mysite.com

Use VHost vhost.mysite.com 80

1
Ах, это похоже на то, что мне нужно. Жаль, что это не встроено ... Но я думаю, я могу жить. Спасибо!
Дэвид Волевер

3
Отлично! Это делает то, что я планировал сделать гораздо лучше, чем я думал, было бы возможно сделать.
SpoonMeiser

5
@SpoonMeiser Этот модуль интегрирован в HTTP-сервер Apache версии 2.4.6. httpd.apache.org/docs/current/mod/mod_macro.html
Людвиг

24

Гораздо проще, используя Defineключевое слово. Смотрите определение директивы .

Define RVM_ROOT /opt/rvmdir/gems
Define RUBY_18 ruby-1.8.7-head

...

SetEnv GEM_HOME ${RVM_ROOT}/${RUBY_18}@typo55
SetEnv GEM_PATH ${RVM_ROOT}/${RUBY_18}@typo55:${RVM_ROOT}/${RUBY_18}@global

2
Отлично. Это прекрасно работает.
Дэвид Тонхофер

Обратите внимание, что The variable is always globally defined and not limited to the scope of the surrounding config section.это, вероятно, означает (я не проверял это сейчас), что если у вас есть несколько vhosts, вы не можете использовать одну и ту же переменную (с другим значением) для каждого.
Пьер-Оливье Варес

@ Pierre-OlivierVares Правильно, смотрите на них как на постоянные. Вот почему я использую заглавные буквы. Я определяю их глобально за пределами VirtualHost
Матье Ж.

14

Вы можете включить или отключить биты конфигурации с IfDefine, но это, вероятно, не будет делать то, что вы хотите. Вместо этого вы можете установить переменные окружения в вашем скрипте инициализации Apache для доступа в конфигурации. Например, добавив:

HOSTNAME=$(hostname)

to /etc/init.d/httpd(перед строкой, которая вызывает httpd!) на машине RHEL передает имя хоста машины в качестве переменной. Это не обязательно должен быть вывод команды - все, что устанавливает переменную в среде, которая запускается httpd, прекрасно. Переменные могут быть использованы в конфигурации следующим образом:

[root@dev ~]# cat /etc/httpd/conf.d/test.conf
Header set X-Hostname ${HOSTNAME}

[root@dev ~]# GET -Sed http://localhost
GET http://localhost --> 200 OK
Connection: close
Date: Fri, 11 Sep 2009 20:47:13 GMT
Server: Apache/2.2.3 (Red Hat)
Content-Length: 525
Content-Type: text/html;charset=ISO-8859-1
Client-Date: Fri, 11 Sep 2009 20:47:13 GMT
Client-Peer: 127.0.0.1:80
Client-Response-Num: 1
Title: Index of /
X-Hostname: dev.local

Конечно, вы не ограничены этой Headerдирективой. Переменные можно использовать где угодно, например, и <Directory ${FOO}>т. Д.

Если вам это не нравится (и это не так приятно), вы можете сгенерировать конфигурацию из шаблона, используя m4 или другой язык шаблонов.

ДОПОЛНИТЕЛЬНО :

Хм, один из способов сделать это лучше - сохранить все переменные во внешнем файле, возможно /etc/httpd/conf/variables.txt:

FOO=/path/to/dir
ROLE=development

и затем включите их в ваш init.dскрипт Apache с помощью:

. /etc/httpd/conf/variables

перед звонком httpd. Все еще не блестящий, но по крайней мере он разделяет сценарий запуска и переменные.


ччмм ... Спасибо - в то время, как вы говорите, это не совсем так хорошо , как я надеялся, что это , безусловно , лучше , чем ничего. Благодарю.
Дэвид Волевер

11
Лучшим (и более чистым) местом для этих переменных среды будет /etc/sysconfig/httpd(RedHat, CentOS) или /etc/apache2/envvars(Ubuntu / Debian). Некоторые переменные окружения уже есть.
Стефан Ласевский,

7

Вы можете использовать системные переменные окружения с mod_env и директивой PassEnv. Глянь сюда

Пример для Debian:

Добавьте вашу переменную в / etc / apache2 / envvars (этот файл используется apache2ctl для определения переменных)

...
export APACHE_PID_FILE=/var/run/apache2.pid
export HOSTNAME=$(hostname)

Передайте вашу переменную в конфигурацию apache

PassEnv HOSTNAME

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

Header set Served-By %{HOSTNAME}e

1
большое спасибо - хотя это не дало мне ответ на apache 2.2 centos 6.4 - это действительно
указало

Для этого требуется mod_define, по умолчанию не загруженный в apache2.2.
Томас

3

У меня была та же проблема, и после некоторых исследований решение для Apache 2.x, которое точно решило ее для меня (и ничего более), было так:

http://people.apache.org/~rjung/mod_define/

Помните, что после распаковки вы должны собрать его так (установочная часть документа, похоже, забыла придерживаться apache2?):

apxs2 -cia mod_define.c

Затем создайте /etc/apache2/mods-available/define.load:

LoadModule define_module /usr/lib/apache2/modules/mod_define.so

После этого включите модуль, a2enmodкак обычно.

Документы в ссылке выше показывают, как его использовать. Теперь вы можете очень просто определить материал и использовать его напрямую, в рамках одного и того же конфига apache2.


В случае, если это неясно, такая же функциональность доступна по умолчанию в Apache 2.4.
ColinM

2

невероятно, но на httpd 2.2 на centos 6.4 это работает

экспортируйте переменные в / etc / sysconfig / httpd

export mydocroot=/var/www/html

тогда просто сделай это ...

<VirtualHost *:80>
  DocumentRoot ${mydocroot}
</VirtualHost>

тогда наконец ....

service httpd restart;

это, вероятно, потому, что (часть) /etc/sysconfig/httpdсодержимого входит в httpd -D(эквивалент defineдирективы), которые определяют переменные apache.

1

Возможно, вы захотите заглянуть в mod_passenger для apache, который также может содержать приложения django. Мы используем его с большим успехом. Все, что вам нужно сделать во Вхосте, это точно ничего. Единственное, что вам нужно, это создать «публичный» dir в корне приложения и создать символические ссылки в «public» на ваши статические каталоги, такие как «media» (это повысит производительность статического обслуживания) и указать на него DocumentRoot.

Затем поместите следующий файл в "public /../ passenger_wsgi.py":

import sys, os
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)
sys.path.append('/PATH/TO/PACKAGES') # optional
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Запустите ваш браузер: он работает!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.