英文:
Environment variables apparently not being passed to a systemd service invocation
问题
以下是翻译好的内容:
这是一个案例:
我正在编写一个 go
程序。
在程序的某个地方,通过 os.Exec()
调用 terragrunt
命令行界面。
该程序在一个安装有 systemd
版本为 232
的机器上运行。
到目前为止,我一直在使用一些暴露的环境变量来调用 terragrunt
(正如我们将在下面看到的那样)。
这些环境变量通过 /etc/profile.d/terragruntvars
将它们传递给登录进程,例如:
export TF_VAR_remote_state_bucket=my-bucket-name
因此,当我在终端中运行 terragrunt plan
并通过我的 tf
/ hcl
文件进行适当的插值时,我会得到类似以下的输出(这是一个 debug
级别的输出,显示了 terragrunt
最终执行的实际 terraform
命令):
terraform init -backend-config=my-bucket-name ...(后面还有更多标志)
我的 go
程序(通过 os.Exec()
调用 terragrunt
命令行界面)通过 go run main.go
完美运行。
我决定将其作为 systemd
服务,如下所示:
[Service]
ExecStart=/bin/sh -c myprogram
EnvironmentFile=/etc/myprogram/config
User=someuser
Group=somegroup
[Install]
WantedBy=multi-user.target
程序开始严重失败。通过搜索根本原因,我发现在运行时 TF_VAR_*
变量从未传递给服务,因此 terraform
命令变成了这样:
terraform init -backend-config=(这是空的,没有任何内容)
我认为通过显式地通过 bash
调用服务,即将 ExecStart=/bin/sh -c myprogram
这样做,可以解决问题。
接下来是最奇怪的部分。
将这些变量添加到 EnvironmentFile=/etc/myprogram/config
没有任何效果 对 terragrunt
的执行。当我说没有效果时,我的意思是这些变量确实对服务可用,但命令仍然是错误的,即:
terraform init -backend-config=(这是空的,没有任何内容)
然而,TF_VAR_*
变量确实存在。我在程序中添加了一个 os.Exec("env")
并打印它们。
这让我抓狂,所以如果有任何关于可能导致此问题的提示,将不胜感激。
英文:
Here is the case:
I am writing a go
program.
At some point, the program calls terragrunt
cli, via os.Exec()
.
The program is run on a machine having systemd
version 232
.
Up till know, I have been invoking terragrunt
with some env vars exposed (required by terragrunt
as we will see below)
These env vars are passed to the login process by /etc/profile.d/terragruntvars
as in
export TF_VAR_remote_state_bucket=my-bucket-name
So when I run in my terminal say terragrunt plan
and by the appropriate interpolation in my tf
/ hcl
files, I get something like (this is a debug
level output, showing the actual terraform
invocation terragrunt
ends up performing)
terraform init -backend-config=my-bucket-name ...(more flags following)
My go
program (invoking terragrunt
cli via os.Exec()
) runs perfectly via go run main.go
I decide to make this a systemd
service as in
[Service]
ExecStart=/bin/sh -c myprogram
EnvironmentFile=/etc/myprogram/config
User=someuser
Group=somegroup
[Install]
WantedBy=multi-user.target
The program started failing miserably. By searching the root case I found out that the TF_VAR_*
variables where never passed to the service when running, so the terraform
command ended up being like
terraform init -backend-config=(this is empty, nothing here)
I thought that by explicitly invoking the service via bash
, i.e. by making ExecStart=/bin/sh -c myprogram
this would address the problem.
Here come the weird(est) parts.
Adding these vars to EnvironmentFile=/etc/myprogram/config
did not have any effect in the terragrunt
execution. When I say no effect, I mean the variables did become available to the service, however the command is still broken, i.e.
terraform init -backend-config=(this is empty, nothing here)
However, the TF_VAR_*
variables ARE there. I added an os.Exec("env")
in my program and it did print them.
This has been driving me nuts so any hint about what might be causing this would be highly appreciated.
答案1
得分: 2
就像一个外壳不会将其进程的环境变量传递给子进程一样:
$ X=abc
$ bash -c 'echo $X' # 什么都不打印
除非你导出环境变量:
$ export X
$ bash -c 'echo $X' # abc
类似地,在使用systemd
和EnvironmentFile
时,要导出环境变量,可以使用PassEnvironment
,例如:
PassEnvironment=VAR1 VAR2 VAR3
来自文档:
> PassEnvironment=
> 将为系统服务管理器设置的环境变量传递给执行的进程。
> 接受一个以空格分隔的变量名列表...
英文:
Just like a shell will not pass it's process ENV VAR's on to child processes:
$ X=abc
$ bash -c 'echo $X' # prints nothing
unless you export the environment variable:
$ export X
$ bash -c 'echo $X' # abc
similarly with systemd
and when using EnvironmentFile
, to export environment variables, use PassEnvironment
e.g.
PassEnvironment=VAR1 VAR2 VAR3
From the docs:
> PassEnvironment=
> Pass environment variables set for the system service manager to executed processes.
> Takes a space-separated list of variable names...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论