如何使用 Docker 和 centos7/httpd 基本映像将 EnvironmentFile 指令添加到 systemctl
How to add EnvironmentFile directive to systemctl using Docker with centos7/httpd base image
我不确定如果不创建我自己的基础映像是否可行,但我在我们的服务器上使用 /etc/environment
中的环境变量,通常通过执行以下操作使 apache 可以访问它们:
$ printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
$ mkdir /usr/lib/systemd/system/httpd.service.d
$ printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
$ systemctl daemon-reload
$ systemctl restart httpd
$ reboot
这些变量随后可用于对 getenv('HTTP_VAR1');
的任何 PHP 调用等。但是,在 运行 中来自 docker 文件的 dbus 错误系统命令。没有 systemctl 命令,变量似乎对 apache 不可用,因为新的 EnvironmentFile 指令似乎没有生效。我的 docker 文件片段:
FROM centos/httpd:latest
RUN printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
RUN mkdir /usr/lib/systemd/system/httpd.service.d &&\
printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
RUN systemctl daemon-reload &&\
systemctl restart httpd
COPY entrypoint.sh /entrypoint.sh
所以我今天偶然发现了这个问题的答案。似乎 systemd 将反斜杠放在单引号内,但从我在测试中看到的情况来看,它也可能会影响双引号。我找到了 systemd development mailing list thread from April 2014 where patching the issue was being discussed。似乎修复从未成功。所以我们必须解决它。
在尝试解决它时,我注意到实际读取变量时存在一些问题。似乎 Apache 或 php-cli 会获得正确的变量,有时根本不会,需要进行一些调查才能弄清楚发生了什么。然后我开始阅读 systemd's EnvironmentFile directive 以查看是否可以从文档中获得更多信息。事实证明它不计算 bash 所以导出不会工作。它需要一个带有变量赋值的文本文件,这里是可能阻止这个问题得到解决的主要问题之一。
然后我设计了一个可行的解决方案。利用 systemd's ExecStartPre directive 我能够 运行 在 httpd 服务启动时的脚本。然后我读入环境文件并编写一个新的纯文本文件,然后由 httpd 的 systemd 单元使用。这是代码:
首先,我将我的变量移动到 /etc/profile.d/
目录而不是 /etc/environment
文件。
文件: /etc/profile.d/environment.sh
这是我们存储所有环境变量的地方,这很容易在所有交互式 shell 登录中获取。在极少数情况下,我们需要以非交互方式提供这些变量,我们可以向 /bin/bash
提供 --login
标志或手动获取它。
export HTTP_VAR1=var1-value-with-a-back\slash
export HTTP_VAR2=var2-value
文件: /usr/lib/systemd/system/httpd.service.d/environment.conf
我们的嵌入式单元文件用于扩展 httpd 服务的工作方式。我在 httpd 启动之前添加了一个 运行s 的脚本。这会在所有 httpd 重新启动和启动时得到 运行。 运行s 的脚本在 /etc/profile.d/environment.env
处生成了一个纯文本文件,我们随后告诉 systemd 将其作为 EnvironmentFile 加载。
[Service]
ExecStartPre=/usr/bin/bash -c "/usr/local/bin/generate-plain-environment-file"
EnvironmentFile=/etc/profile.d/environment.env
文件: /usr/local/bin/generate-plain-environment-file
这是我正在使用的脚本,我非常快地将它组合在一起,我真的不认为它那么健壮并且它可以更好。它只是从行的开头删除 export
,然后转义任何反斜杠,因为 systemd 会删除单个反斜杠。更合适的解决方案可能是使用 bash 评估每一行并在实际 bash 变量中使用变量或其他 bash 的情况下获取变量值,然后将它们输出为普通文本名称=值赋值,但这不是我的用例的一部分,所以我没有打扰。
#!/bin/bash
cd /etc/profile.d/
rm -rf "./environment.env"
while IFS='' read -r line || [[ -n "$line" ]]; do
echo $(echo "${line}" | sed 's/^export //' | sed 's/\/\\/g') >> "./environment.env";
done < "./environment.sh"
文件: /etc/profile.d/environment.env
这是描述的脚本生成的结果文件。
HTTP_VAR1=var1-value-with-a-back\slash
HTTP_VAR2=var2-value
结论是,我现在有两个文件,里面有相同的东西,但我只需要维护一个,另一个是每次重新启动 httpd 时生成的。此外,我们在此过程中修复了反斜杠问题。万岁!
我不确定如果不创建我自己的基础映像是否可行,但我在我们的服务器上使用 /etc/environment
中的环境变量,通常通过执行以下操作使 apache 可以访问它们:
$ printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
$ mkdir /usr/lib/systemd/system/httpd.service.d
$ printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
$ systemctl daemon-reload
$ systemctl restart httpd
$ reboot
这些变量随后可用于对 getenv('HTTP_VAR1');
的任何 PHP 调用等。但是,在 运行 中来自 docker 文件的 dbus 错误系统命令。没有 systemctl 命令,变量似乎对 apache 不可用,因为新的 EnvironmentFile 指令似乎没有生效。我的 docker 文件片段:
FROM centos/httpd:latest
RUN printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
RUN mkdir /usr/lib/systemd/system/httpd.service.d &&\
printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
RUN systemctl daemon-reload &&\
systemctl restart httpd
COPY entrypoint.sh /entrypoint.sh
所以我今天偶然发现了这个问题的答案。似乎 systemd 将反斜杠放在单引号内,但从我在测试中看到的情况来看,它也可能会影响双引号。我找到了 systemd development mailing list thread from April 2014 where patching the issue was being discussed。似乎修复从未成功。所以我们必须解决它。
在尝试解决它时,我注意到实际读取变量时存在一些问题。似乎 Apache 或 php-cli 会获得正确的变量,有时根本不会,需要进行一些调查才能弄清楚发生了什么。然后我开始阅读 systemd's EnvironmentFile directive 以查看是否可以从文档中获得更多信息。事实证明它不计算 bash 所以导出不会工作。它需要一个带有变量赋值的文本文件,这里是可能阻止这个问题得到解决的主要问题之一。
然后我设计了一个可行的解决方案。利用 systemd's ExecStartPre directive 我能够 运行 在 httpd 服务启动时的脚本。然后我读入环境文件并编写一个新的纯文本文件,然后由 httpd 的 systemd 单元使用。这是代码:
首先,我将我的变量移动到 /etc/profile.d/
目录而不是 /etc/environment
文件。
文件: /etc/profile.d/environment.sh
这是我们存储所有环境变量的地方,这很容易在所有交互式 shell 登录中获取。在极少数情况下,我们需要以非交互方式提供这些变量,我们可以向 /bin/bash
提供 --login
标志或手动获取它。
export HTTP_VAR1=var1-value-with-a-back\slash
export HTTP_VAR2=var2-value
文件: /usr/lib/systemd/system/httpd.service.d/environment.conf
我们的嵌入式单元文件用于扩展 httpd 服务的工作方式。我在 httpd 启动之前添加了一个 运行s 的脚本。这会在所有 httpd 重新启动和启动时得到 运行。 运行s 的脚本在 /etc/profile.d/environment.env
处生成了一个纯文本文件,我们随后告诉 systemd 将其作为 EnvironmentFile 加载。
[Service]
ExecStartPre=/usr/bin/bash -c "/usr/local/bin/generate-plain-environment-file"
EnvironmentFile=/etc/profile.d/environment.env
文件: /usr/local/bin/generate-plain-environment-file
这是我正在使用的脚本,我非常快地将它组合在一起,我真的不认为它那么健壮并且它可以更好。它只是从行的开头删除 export
,然后转义任何反斜杠,因为 systemd 会删除单个反斜杠。更合适的解决方案可能是使用 bash 评估每一行并在实际 bash 变量中使用变量或其他 bash 的情况下获取变量值,然后将它们输出为普通文本名称=值赋值,但这不是我的用例的一部分,所以我没有打扰。
#!/bin/bash
cd /etc/profile.d/
rm -rf "./environment.env"
while IFS='' read -r line || [[ -n "$line" ]]; do
echo $(echo "${line}" | sed 's/^export //' | sed 's/\/\\/g') >> "./environment.env";
done < "./environment.sh"
文件: /etc/profile.d/environment.env
这是描述的脚本生成的结果文件。
HTTP_VAR1=var1-value-with-a-back\slash
HTTP_VAR2=var2-value
结论是,我现在有两个文件,里面有相同的东西,但我只需要维护一个,另一个是每次重新启动 httpd 时生成的。此外,我们在此过程中修复了反斜杠问题。万岁!