Назад | Перейти на главную страницу

Использование IfDefine с переменными среды

Я пытаюсь сделать свою конфигурацию максимально гибкой и простой в настройке, используя список переменных в /etc/sysconfig и загрузка переменных среды при запуске Apache с использованием файла конфигурации drop-in systemd. Поскольку переменные среды не меняются после запуска сервера, я хочу повысить производительность и гибкость, используя Apache IfDefine директива вместо обычного If директива.

Одна из проблем с обычным <If>... </If> директива заключается в том, что директивы внутри блока всегда оценен даже если они не казнен. Это очень важно, если вы используете переменные среды в качестве параметров, например:

SVNParentPath ${MY_SVN_REPOSITORIES_PATH}

В этом случае Apache выдаст ошибку и откажется запускаться, если ${MY_SVN_REPOSITORIES_PATH} оценивается как пустая строка. Я хочу отключить обслуживание репозиториев, когда переменная системной среды MY_SVN_REPOSITORIES_PATH пусто или не задано. Как мне это сделать?

Это ужасный прием, но он сработает. Здесь мы используем 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} если переменная среды не задана), то параметр конфигурации «Тест» (сам по себе) не будет определен.

Здесь есть одно ограничение: мы можем протестировать конкретные значения, включая пустую строку, но мы не можем проверить, не установлена ​​ли переменная, используя только IfDefine директива. Это связано с тем, что невозможно поместить буквальные символы знака доллара и скобок в символ. IfDefine директива без попытки Apache расширить их1. Без escape-символа вы никогда не узнаете, сравнивает ли 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 директивы с операцией ИЛИ, поэтому "не задано" и "пустая строка" застряли как отдельные блоки, но вы можете либо скопировать и вставить свою конфигурацию между блоками, либо проверить mod_macro.


  1. Я проверил исходный код Apache. Функция ap_resolve_env в core.c, а функции, которые его вызывают, по-видимому, отключают вызов только тогда, когда установлен переключатель времени компиляции.