process.env.PATH 乘客节点应用程序中未定义(生产模式)
process.env.PATH undefined in Passenger node app (production mode)
我最近用 Phusion Passenger 为 nginx 部署了一个节点应用程序,在这个过程中遇到了一个非常古怪的错误:
我的代码在尝试生成 child_process 时抛出错误。我做了一些调试,最终得出结论,问题出在节点中未定义的 $PATH
环境变量,我可以用这样的 passenger_env_var
指令解决问题(显示我的 nginx 的摘录配置):
server {
listen 80;
server_name blargh.com;
root /home/user/blargh.com/build;
passenger_enabled on;
# For some reason $PATH isn't loaded into node, and we can't spawn child processes without it
passenger_env_var PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games;
}
我仍然没有弄清楚是什么导致了这个问题 - 设置 passenger_load_shell_envvars on;
没有帮助,并且 www-data 用户确实在 [=27] 中定义了一个 $PATH
envvar =].此外,其他环境变量(如 $SHELL
)似乎已由节点加载,增加了为什么 $PATH
被排除在外的谜团。
有人知道是什么导致了这个问题吗?
tl;dr
Specify global envvars that you expect to be defined at system boot (like PATH
) in /etc/default/nginx
. Use something like dotenv properly and write environment specific config for your app in a text file that's not checked in. Environment variables are pretty evil in general.
我觉得这个问题应该得到一个相当长的回答,因为在过去的几个月里,环境变量对我造成了反复出现的问题。
将您的配置存储为环境变量是 12 factor app 为编写可伸缩 Web 应用程序制定的规则之一。它们很好,因为它们可以让您以灵活的方式将配置与代码分开。然而,它们的一个问题是我们通常遇到它们的方式,当我们 export MYVAR=myvalue
或将它们设置在我们的 ~/.pam_environment
或 ~/.bashrc
时, 它们的范围是我们的当前终端会话.
这会导致问题,因为我们开始使用 Phusion Passenger 等解决方案在系统启动时启动我们的应用程序 - 它们的启动脚本不关心用户 shell 环境。他们显然也不关心全局 /etc/environment
,这就是导致我的 PATH
未定义问题的原因。
Phusion Passenger 实际上有一些关于 making global environment variables persist 的文档:
If you installed Nginx through the Debian or Ubuntu packages, then you can define environment variables in /etc/default/nginx
. This is a shell script so you must use the export FOO=bar
syntax.
因此,通过在 /etc/default/nginx
中设置 PATH
环境变量,我可以解决该问题。但是我仍然遇到其他环境变量的问题 - 我必须在我的 nginx 配置中设置它们才能将它们传递到我的节点应用程序。我很清楚这不是正确的方法。
此时我已经在使用 dotenv,但我稍微误解了它的用途。我检查了 .env
文件,并将其视为一种为环境变量提供默认值的方式,这些默认值将根据需要被环境覆盖。这不是作者自己设想的使用此模块的方式:
We strongly recommend against committing your .env file to version control. It should only include environment-specific values such as database passwords or API keys.
我开始越来越清楚,人们通常不会在实际环境中为他们的应用程序定义环境变量。我发现 Peter Lyons 的 an article 建议将配置存储在文本文件中而不是在 envvars 中,这就是我点击它的时候。
我的最终解决方案是取消提交我的 .env
文件,并为每个环境编写一个特定的文件。我在我的回购协议中留下了一个 .env.template
作为我的应用程序预期在 运行 时定义的配置的参考。
我最近用 Phusion Passenger 为 nginx 部署了一个节点应用程序,在这个过程中遇到了一个非常古怪的错误:
我的代码在尝试生成 child_process 时抛出错误。我做了一些调试,最终得出结论,问题出在节点中未定义的 $PATH
环境变量,我可以用这样的 passenger_env_var
指令解决问题(显示我的 nginx 的摘录配置):
server {
listen 80;
server_name blargh.com;
root /home/user/blargh.com/build;
passenger_enabled on;
# For some reason $PATH isn't loaded into node, and we can't spawn child processes without it
passenger_env_var PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games;
}
我仍然没有弄清楚是什么导致了这个问题 - 设置 passenger_load_shell_envvars on;
没有帮助,并且 www-data 用户确实在 [=27] 中定义了一个 $PATH
envvar =].此外,其他环境变量(如 $SHELL
)似乎已由节点加载,增加了为什么 $PATH
被排除在外的谜团。
有人知道是什么导致了这个问题吗?
tl;dr Specify global envvars that you expect to be defined at system boot (like
PATH
) in/etc/default/nginx
. Use something like dotenv properly and write environment specific config for your app in a text file that's not checked in. Environment variables are pretty evil in general.
我觉得这个问题应该得到一个相当长的回答,因为在过去的几个月里,环境变量对我造成了反复出现的问题。
将您的配置存储为环境变量是 12 factor app 为编写可伸缩 Web 应用程序制定的规则之一。它们很好,因为它们可以让您以灵活的方式将配置与代码分开。然而,它们的一个问题是我们通常遇到它们的方式,当我们 export MYVAR=myvalue
或将它们设置在我们的 ~/.pam_environment
或 ~/.bashrc
时, 它们的范围是我们的当前终端会话.
这会导致问题,因为我们开始使用 Phusion Passenger 等解决方案在系统启动时启动我们的应用程序 - 它们的启动脚本不关心用户 shell 环境。他们显然也不关心全局 /etc/environment
,这就是导致我的 PATH
未定义问题的原因。
Phusion Passenger 实际上有一些关于 making global environment variables persist 的文档:
If you installed Nginx through the Debian or Ubuntu packages, then you can define environment variables in
/etc/default/nginx
. This is a shell script so you must use the exportFOO=bar
syntax.
因此,通过在 /etc/default/nginx
中设置 PATH
环境变量,我可以解决该问题。但是我仍然遇到其他环境变量的问题 - 我必须在我的 nginx 配置中设置它们才能将它们传递到我的节点应用程序。我很清楚这不是正确的方法。
此时我已经在使用 dotenv,但我稍微误解了它的用途。我检查了 .env
文件,并将其视为一种为环境变量提供默认值的方式,这些默认值将根据需要被环境覆盖。这不是作者自己设想的使用此模块的方式:
We strongly recommend against committing your .env file to version control. It should only include environment-specific values such as database passwords or API keys.
我开始越来越清楚,人们通常不会在实际环境中为他们的应用程序定义环境变量。我发现 Peter Lyons 的 an article 建议将配置存储在文本文件中而不是在 envvars 中,这就是我点击它的时候。
我的最终解决方案是取消提交我的 .env
文件,并为每个环境编写一个特定的文件。我在我的回购协议中留下了一个 .env.template
作为我的应用程序预期在 运行 时定义的配置的参考。