Upstart env 节没有为 Node.js 应用程序设置环境变量(如 NODE_ENV)

Posted

技术标签:

【中文标题】Upstart env 节没有为 Node.js 应用程序设置环境变量(如 NODE_ENV)【英文标题】:Upstart env stanza not setting environment variables (like NODE_ENV) for Node.js application 【发布时间】:2012-02-12 17:49:33 【问题描述】:

我的服务器有一个 Upstart 脚本,如下所示:

description "myapp node.js server"

start on runlevel [2345]
stop on shutdown

env NODE_ENV=production
env CUSTOM=somevalue
exec sudo -u nodejs /usr/local/bin/node /opt/myapp/app.js >> /var/log/nodejs/myapp.log 2>&1

post-start script
    NODE_PID=`status myapp | egrep -oi '([0-9]+)$' | head -n1` 
    echo $NODE_PID > /var/run/nodejs/myapp.pid
end script

但是,该应用没有看到 NODE_ENV 设置为生产。事实上,如果我在应用程序中使用 console.log(process.env),我看不到 NODE_ENV 或 CUSTOM。有什么想法吗?

顺便说一句,NODE_ENV=production node app.js 工作正常。

【问题讨论】:

彼得莱昂斯的回答深入探讨并提供了一些最佳实践建议,但如果我切换到使用“www-data”用户与我自己的“nodejs”用户。后者还不起作用,但这与这个问题有些无关。 我还要提一下,sudo -E(保留环境)可以尝试,虽然我自己没有测试过。 【参考方案1】:

visudo 有一行定义要保留的环境变量。

sudo visudo

并将您的环境添加到:

Defaults        env_keep="YOUR_ENV ..."

然后重启。

【讨论】:

【参考方案2】:

来自sudo man page(Ubuntu 版本的 sudo)

有两种不同的方式来处理环境变量。默认情况下, env_reset sudoers 选项已启用。这会导致在包含 TERM 的最小环境中执行命令, PATH、HOME、SHELL、LOGNAME、USER 和 USERNAME 以及来自调用过程的变量 env_check 和 env_keep sudoers 选项允许。实际上有一个白名单 环境变量。

Sudo 正在重置环境。这是在 upstart 或 init 脚本中使用 susudo 的一个令人沮丧的方面。最新版本的新贵支持在不使用 sudo 的情况下通过 setuid/setgid 指令指定 uid/gid,如下例所示。还要注意chdir的使用。

start on filesystem and started networking
respawn
chdir /var/www/yourapp
setuid yourapp
setgid yourapp
env NODE_ENV=production
env PATH=/usr/local/bin:/usr/bin:/bin
env CUSTOM=somevalue
exec /usr/local/bin/node app.js | /usr/bin/multilog s1024000 /var/log/yourapp 2>&1

对于旧版本的暴发户,这是我用来解决它的方法。

description "start and stop the example.com node.js server"

start on filesystem and started networking
respawn

chdir /path/to/your/code
exec su -c 'PATH=$PWD/node/bin NODE_ENV=$(cat node_env.txt) ./node/bin/node app/server.js' www-data  >> tmp/stdout.log 2>&1

请注意,我只是在我的应用根目录中放置了一个 node_env.txt 文件来设置生产模式,因为 I hate environment variables。如果您愿意,可以直接在此处输入NODE_ENV=production

【讨论】:

几个问题:(1)node_env.txt 里有什么,只是“生产”? (2) 为什么将 PATH 设置为 $PWD/node/bin?并使用./node/bin/node。您是否为您的应用程序安装了本地节点? (3) 为什么使用 su -c 与 sudo -u?谢谢。 node_env.txt 仅包含单个单词“production”(带有尾随换行符)。就这样。是的,我在我的应用程序根目录中安装了节点,我认为这是最佳实践。我在同一台服务器上有许多应用程序,每个应用程序都需要不同的节点版本。我从不共享我的应用服务器堆栈的版本。您应该在 upstart 脚本中使用“su”而不是 sudo,因为它们已经由操作系统以 root 身份运行,并且您不需要 sudo。 “su”在这里是合适的 - 成为不同的用户。 “sudo”更多的是让普通用户以root身份执行特定命令,此处不适用 我将代码切换为使用 exec su -c '...' nodejs >> ... 我现在无法启动该过程。如果我在 shell 中手动运行该命令,系统会要求我输入密码。我用用户 www-data 尝试了手动命令,它要求输入密码。然后我 sudo su -c ... 使用 www-data 并且它起作用了。我还没有尝试在我的 Upstart 脚本中使用 www-data。关于 Linux 用户配置,我在这里缺少什么? 如果您以非 root 身份执行 su,这就是它的工作原理。以root身份运行它,它不会提示输入密码。因此,要从 shell 进行交互式测试,首先执行“sudo su -”成为 root,然后运行 ​​su 命令,就像它在你的 upstart 文件中一样。 我不同意“环境变量是有害的”。它们在代码开发和服务器部署配置之间提供了一个可靠的接口。当与适当的 devops 策略(如 chef)结合使用时,可以在所有正确的位置可靠地设置环境变量 - 使部署可以轻松更改配置,而无需在源代码文件夹中四处寻找。【参考方案3】:

仅作记录。当您的 Upstart 版本实现 setuid 时,Upstart Cookbook 建议使用 the usage of start-stop-daemon 而不是 susudo

但是,除非您仍在使用只有 Upstart 版本 0.6.5 的 10.04 LTS (Lucid Lynx),否则您应该使用 setuid/setgid 指令。

【讨论】:

这不完全正确(还有吗?)从 Upstart 1.4 开始,Upstart 能够使用 setuidsetgid 节以指定用户身份运行系统作业。 我知道这一点,谢谢。但你让我意识到答案可能不够清楚。【参考方案4】:

这一直对我在新贵中设置节点环境变量有用。

#!upstart

start on runlevel [2345]
stop on runlevel [016]

respawn

script
    echo $$ > /var/run/app.pid
    exec sudo NODE_ENV=production /opt/node/bin/node /opt/myapp/app.js >> /var/log/app.sys.log 2>&1
end script

【讨论】:

以上是关于Upstart env 节没有为 Node.js 应用程序设置环境变量(如 NODE_ENV)的主要内容,如果未能解决你的问题,请参考以下文章

Node.js里面怎么设置process.env.PORT的值

如何使用 Amazon EC2 实例为生产设置 node.js process.env 变量?

Node.JS 错误 - process.env.NODE_TLS_REJECT_UNAUTHORIZED。这是啥意思?

Node.js 无法识别 .env 中的任何变量

如何在 node.js 中存根 process.env?

你怎么得到运行Node.js脚本的cron作业从.env文件中读取变量?