是否可以在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
…


谢谢!

#1 楼

您可以使用mod_macro,它自2.4版起就包含在Apache httpd中。

在必须单独安装它之前,请参见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


评论


啊,看起来像我需要的。可惜它不是内置的...但是我想我可以活下去。谢谢!

– David Wolever
09年9月12日23:58

@SpoonMeiser该模块从版本2.4.6集成到Apache HTTP Server中。 httpd.apache.org/docs/current/mod/mod_macro.html

–路德维希
2014年4月30日在7:57

在您的示例中,您具有与DocumentRoot / var / vhosts / $ host和相同的路径。我有类似的情况,我想定义hostpath = / var / vhosts / $ host,并使用DocumentRoot $ {hostpath}和。有没有好的方法可以做到这一点?还是在使用宏中的变量后应该使用Define hostpath / var / vhosts / $ host和UnDefine hostpath?

– RjOllos
19年11月22日在17:37



#2 楼

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


评论


请注意,变量始终是全局定义的,并且不限于周围的config部分的范围。这可能意味着(我暂时尚未测试),如果您有多个虚拟主机,则不能为每个虚拟主机使用相同的变量(值不同)。

– Pierre-Olivier Vares
19年7月4日在8:41

@ Pierre-OlivierVares正确,将其视为常量。这就是为什么我使用大写字母。我在VirtualHost之外全局定义它们

– Mathieu J.
19年7月4日在10:43

使用Apache / 2.4.46进行的测试清楚地表明,Define定义变量,而不是常量。重新定义相同的名称可以正常工作,不会更改变量的当前值。因此,如简单测试所示,使用Define和Include定义虚拟主机之类的东西效果很好。宏也应该工作(尽管没有测试它们)。

–David Spector
1月5日15:39



#3 楼

您可以使用IfDefine启用或禁用一些配置,但这可能无法满足您的要求。相反,您可以在Apache初始化脚本中设置环境变量以在配置内进行访问。例如,在RHEL机器上将
HOSTNAME=$(hostname)
添加到/etc/init.d/httpd(在调用httpd!的行之前)之前,将机器的主机名作为变量传递进来。它不一定是命令的输出-在启动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或其他某种模板语言从模板生成配置。

附加项:

Hrm,一种更好的方法是将所有变量存储在外部文件中,也许是/etc/httpd/conf/variables.txt

FOO=/path/to/dir
ROLE=development


,然后将它们包含在Apache init.d脚本中,并包含以下内容:

. /etc/httpd/conf/variables


,然后调用httpd。仍然不够出色,但至少它可以将启动脚本和变量分开。

评论


这些环境变量的更好(更干净)的地方是/ etc / sysconfig / httpd(RedHat,CentOS)或/ etc / apache2 / envvars(Ubuntu / Debian)。已经有一些环境变量。

– Stefan Lasiewski
2011年4月22日在23:41

#4 楼

您可以将系统环境变量与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


评论


非常感谢-尽管这无法为我在apache 2.2 centos 6.4上提供答案-确实为我指明了正确的方向+1

– danday74
16-4-14在14:57



这需要mod_define,默认情况下未在apache2.2中加载。

–托马斯
18-10-18在19:18

#5 楼

我遇到了同样的问题,经过研究后,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
13年5月7日在22:16

#6 楼

令人难以置信,但是在centos 6.4上的httpd 2.2上却行得通。

在/ etc / sysconfig / httpd

export mydocroot=/var/www/html


中导出环境变量,然后只需执行此操作即可。 ..

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


然后终于....

service httpd restart;


评论


这可能是因为/ etc / sysconfig / httpd内容中的某些内容进入了定义apache变量的httpd -D(相当于define指令)。

–user246890
19-2-26在13:27



#7 楼

您可能要研究mod_passenger for apache,它也可以托管Django应用程序。我们成功地使用了它。在虚拟主机中您需要做的就是,完全没有任何事情。您唯一需要做的就是在应用程序根目录中创建一个“ public”目录,并在“ 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()


启动浏览器:它可以工作!