Upstart env stanza not setting environment variabl

2020-02-17 05:57发布

问题:

I have an Upstart script for my server that looks like this:

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

However, the app doesn't see NODE_ENV set to production. In fact, if I console.log(process.env) within the app, I don't see NODE_ENV or CUSTOM. Any ideas what's happening?

By the way, NODE_ENV=production node app.js works just fine.

回答1:

From the sudo man page (Ubuntu version of sudo)

There are two distinct ways to deal with environment variables. By default, the env_reset sudoers option is enabled. This causes commands to be executed with a minimal environment containing TERM, PATH, HOME, SHELL, LOGNAME, USER and USERNAME in addition to variables from the invoking process permitted by the env_check and env_keep sudoers options. There is effectively a whitelist for environment variables.

Sudo is resetting the environment. This is a frustrating aspect of using su and sudo in upstart or init scripts. Recent versions of upstart support specifying uid/gid without the use of sudo via the setuid/setgid directives as in the example below. Also note the use of 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

For older versions of upstart, here's what I used to do to work around it.

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

Note that I just put a node_env.txt file in my app root that sets production mode, because I hate environment variables. You can just do NODE_ENV=production right there if you prefer.



回答2:

Just for the record. The Upstart Cookbook recommends the usage of start-stop-daemon instead of su or sudo when your Upstart version does not implement setuid.

But, unless you are still using 10.04 LTS (Lucid Lynx) which only has Upstart version 0.6.5, you should be using the setuid/setgid directives.



回答3:

This has been working for me to set node env variables in upstart.

#!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


回答4:

visudo has a line to define environment variables to be kept.

sudo visudo

and add your env to:

Defaults        env_keep="YOUR_ENV ..."

and reboot.