在乘客节点应用程序(生产模式)中未定义process.env.PATH

时间:2015-04-15 14:10:18

标签: node.js nginx passenger

我最近使用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用户确实在shell中定义了$PATH envvar。此外,其他环境变量(如$SHELL)似乎已被节点加载,这增加了为什么$PATH被排除在外的谜团。

有人知道可能导致此问题的原因吗?

1 个答案:

答案 0 :(得分:1)

  

<强> TL;博士   指定您希望在PATH中的系统引导时定义的全局envvars(如/etc/default/nginx)。正确使用dotenv之类的内容,并在未签入的文本文件中为您的应用编写特定于环境的配置。环境变量通常非常恶劣。

我觉得这个应该得到一个相当冗长的答案,因为环境变量在过去几个月里给我带来了反复出现的问题。

将配置存储为环境变量是12 factor app编写可伸缩Web应用程序的规则之一。它们很好,因为它们允许您以灵活的方式将配置与代码分开。但是,它们的问题在于我们正常遇到它们的方式,当我们export MYVAR=myvalue或将它们设置在~/.pam_environment~/.bashrc时,它们的范围是我们当前的终端会话

当我们开始使用Phusion Passenger等解决方案在系统启动时启动我们的应用程序时,这会导致问题 - 他们的启动脚本不关心用户shell环境。他们也显然不关心全局/etc/environment,这是导致我PATH未定义的问题。

Phusion Passenger实际上有making global environment variables persist的一些文档:

  

如果您通过Debian或Ubuntu软件包安装了Nginx,那么您可以在/etc/default/nginx中定义环境变量。这是一个shell脚本,因此您必须使用导出FOO=bar语法。

因此,通过在PATH中设置/etc/default/nginx envvar,我可以解决该问题。但我仍然遇到其他环境变量的问题 - 我必须在我的nginx配置中设置它们以将它们传递给我的节点应用程序。我很清楚,这不是正确的做法。

此时我已经在使用dotenv了,但我稍微误解了它的用途。我已经检查了.env文件并将其视为一种为envvars提供默认值的方法,这些默认值将根据需要被环境覆盖。这不是作者自己设想使用这个模块的方式:

  

我们强烈建议您不要将.env文件提交给版本控制。它应该只包含特定于环境的值,例如数据库密码或API密钥。

我开始明白,人们通常不会在实际环境中为他们的应用定义envvars。我发现Peter Lyons的an article建议将配置存储在文本文件而不是envvars中,这就是它为我点击的时候。

我的最终解决方案是取消提交我的.env文件,并为每个环境编写一个特定的文件。我在我的仓库中留下了.env.template,作为我的应用程序预期在运行时定义的配置的参考。