我试图通过使用变量列表并在使用 systemd 插入配置文件启动 Apache 时加载环境变量,使我的配置尽可能灵活且易于配置。由于环境变量在服务器启动后不会改变,因此我想通过使用 Apache 的指令而不是常规指令/etc/sysconfig
来提高性能和灵活性。IfDefine
If
常规指令的一个问题<If>... </If>
是,块内的指令总是评估即使他们不是执行。如果您使用环境变量作为参数,这一点非常重要,如下所示:
SVNParentPath ${MY_SVN_REPOSITORIES_PATH}
${MY_SVN_REPOSITORIES_PATH}
在这种情况下,如果计算结果为空字符串,Apache 将抛出错误并拒绝启动。我想在系统环境变量MY_SVN_REPOSITORIES_PATH
为空或未设置时禁用服务存储库。我该怎么做?
答案1
这是一个丑陋的 hack,但它可以工作。我们在这里做的是使用Define
指令来定义一个变量,其姓名包括价值环境变量,然后检查该变量是否定义:
Define "Test${MY_SVN_REPOSITORIES_PATH}"
<IfDefine Test>
# the variable is set to an empty string
</IfDefine>
<IfDefine !Test>
# SVN repositories are configured or the variable is unset
</IfDefine>
<IfDefine "Test/srv/svn">
# SVN repositories are configured to be in /srv/svn
</IfDefine>
如果${MY_SVN_REPOSITORIES_PATH}
计算结果为空字符串,则将定义配置参数“Test”。如果环境变量计算结果为其他值(如果环境变量未设置,则可能是文字${MY_SVN_REPOSITORIES_PATH}
),则不会定义配置参数“Test”(本身)。
这里有一个限制:我们可以测试具体价值,包括一个空字符串,但我们无法仅使用指令来测试变量是否未设置IfDefine
。这是因为没有办法将文字美元符号和括号字符放入指令中,IfDefine
而不会让 Apache 尝试扩展它们1。如果没有转义字符,您永远不会知道 Apache 是在与文字变量名称进行比较,还是与它的值进行比较。
但是,也有一个丑陋的办法可以解决这个问题!
# Prevent environment variable expansion by splitting the variable name into two literals
Define FirstPartOfVariableName "${MY_SVN_"
Define SecondPartOfVariableName "REPOSITORIES_PATH}"
Define "Test${MY_SVN_REPOSITORIES_PATH}"
<IfDefine "Test">
# Environment variable is set to an empty string
</IfDefine>
<IfDefine Test${FirstPartOfVariableName}${SecondPartOfVariableName}>
# Environment variable is not set
</IfDefine>
<IfDefine !Test>
<IfDefine !Test${FirstPartOfVariableName}${SecondPartOfVariableName}>
# The environment variable is set, and is not an empty string.
</IfDefine>
</IfDefine>
在这里,我们绕过了环境变量扩展,以便我们能够识别配置过程中我们关心的三种主要情况。您不能IfDefine
使用 OR 运算组合指令,因此“未设置”和“空字符串”只能作为单独的块,但您可以在块之间复制和粘贴配置,也可以签出mod_macro。
- 我检查了 Apache 的源代码。该函数位于
ap_resolve_env
中core.c
,并且调用它的函数似乎仅在设置了编译时开关时才禁用该调用。