将 IfDefine 与环境变量结合使用

use*_*147 3 environment-variables apache-2.4 apache2

/etc/sysconfig我试图通过使用变量列表并在使用 systemd 嵌入式配置文件启动 Apache 时加载环境变量,使我的配置尽可能灵活且易于配置。由于环境变量在服务器启动后不会改变,因此我想通过使用 Apache 的IfDefine指令而不是常规If指令来提高性能和灵活性。

常规指令的问题之一<If>... </If>是块内的指令即使没有被执行也总是被计算。如果您使用环境变量作为参数,这一点非常重要,如下所示:

SVNParentPath ${MY_SVN_REPOSITORIES_PATH}
Run Code Online (Sandbox Code Playgroud)

${MY_SVN_REPOSITORIES_PATH}在这种情况下,如果计算结果为空字符串,Apache 将抛出错误并拒绝启动。我想在系统环境变量MY_SVN_REPOSITORIES_PATH为空或未设置时禁用服务存储库。我该怎么做呢?

use*_*147 7

这是一个丑陋的黑客,但它会起作用。我们在这里所做的是使用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>
Run Code Online (Sandbox Code Playgroud)

如果${MY_SVN_REPOSITORIES_PATH}计算结果为空字符串,则将定义配置参数“Test”。如果环境变量的计算结果为其他内容(${MY_SVN_REPOSITORIES_PATH}如果未设置环境变量,则可能是文字),则将不会定义配置参数“Test”(单独)。

这里有一个限制:我们可以测试特定值,包括空字符串,但我们不能仅使用指令来测试变量是否未设置IfDefineIfDefine这是因为如果 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>
Run Code Online (Sandbox Code Playgroud)

在这里,我们绕过了环境变量扩展,以便我们可以识别配置过程中我们关心的三种主要情况。您不能将IfDefine指令与 OR 运算组合在一起,因此“未设置”和“空字符串”被困在单独的块中,但您可以在块之间复制并粘贴您的配置或查看mod_macro


  1. 我检查了Apache的源代码。该函数位于ap_resolve_envcore.c,调用它的函数似乎仅在设置编译时开关时禁用该调用。