7

How does one go about getting a new environment variable picked up system-wide without restarting the server?

As its an Ubuntu 11.x server, I'm using Upstart to start/restart processes.

I added a new environment variable to /etc/environment that needs to be picked up by one of my app's processes.

If I start the process directly from my shell, the variable is being picked up and all is fine (I've already sourced /etc/environment for my session). However, when I start/restart the process using its Upstart service name, the variable is not being seen.

 sudo start app-name

I'm pretty sure that if I restarted the server the new variable will get picked up, however I would like to try to avoid that. I have some other live processes running on it that I'd like to avoid interrupting if at all possible.

Geuis
  • 625
  • 3
  • 8
  • 17

3 Answers3

3

This question seems to contain a lot of sub-questions about how to handle environment variables in an Upstart script, so I thought I would share a few things I do to handle and test my environment for Upstart and Cron.

The first thing to know about Upstart, and the like, is it does not share the same environment as your active terminal, so something like:

$ export FOO=bar
$ start upstart-name

does not work because upstart-name will not actually see the FOO you just exported into the current shell because Upstart runs in a clean environment.

You can mimic the clean environment that Upstart (and Cron) runs in with this handy method that I cribbed from another answer many moons ago:

# makes the current shell have an environment like cron or upstart
# http://stackoverflow.com/a/2546509/5006
function cronenv() {
  cron_env+="HOME=$HOME\n"
  cron_env+="LOGNAME=$LOGNAME\n"
  cron_env+="PATH=/usr/bin:/bin\n"
  cron_env+="SHELL=/bin/sh\n"
  cron_env+="PWD=$PWD\n"

  if [[ -n $LC_ALL ]]; then
    cron_env+="LC_ALL=$LC_ALL\n"
  fi

  env - `echo -e $cron_env` /bin/sh
}

Just dump that in your .bash_profile or the like and you can run commands as Upstart would run them:

$ cronenv
$ some/big/command --to --run --as --upstart

Now, let's actually set up a shared environment on our box, we'll do that by putting our environment variables in /etc/profile.d/environ.sh

# /etc/profile.d/environ.sh
export FOO=bar

and then sourcing that in our Upstart script:

script
  # source our common environment file
  . /etc/profile.d/environ.sh
  exec some/big/command --to --run --as --upstart
end script

Now we'll be able to "see" our environment on any shell and any Upstart script that sources our common file (by default, ssh on Ubuntu will source everything from /etc/profile.d). Yay!

Jaymon
  • 273
  • 2
  • 9
2

Put the env stanza in your upstart job description file.

http://upstart.ubuntu.com/wiki/Stanzas#env

env PIDFILE=/var/run/myprocess.pid

Or whatever. It's all in the documentation.

Tom O'Connor
  • 27,440
  • 10
  • 72
  • 148
  • Thanks, I can totally make that work. I'd like to go further and make it global and permanent though. I'm setting a variable that multiple processes can use to determine if they're in a development or production environment. The conf file will work for now because I develop on a Mac, but I eventually will have an integration environment running Ubuntu and each server will run multiple separate app processes. It would be convenient for them all not to rely on the confs. – Geuis Dec 17 '11 at 11:09
  • What? You wanna use Upstart. Good. You need to specify things in the Upstart's configuration so that it knows how to start the processes. It's either that, or you make a wrapper script that sets and exports environment variables (messy) Or modify the default bash profile, so they're always set and exported (Insanely Messy). – Tom O'Connor Dec 17 '11 at 11:12
  • The *right* way to do this is to use something like Puppet to manage your different environments, and then Puppet can manage the different configuration files, across many servers, without fuss. – Tom O'Connor Dec 17 '11 at 11:13
  • Tom, I'm running into an odd problem. Using env, I can't set any custom environment variables. If I set system defined vars, they are being read by the app. But my own aren't. For example, I set without quotes in the conf, "env DISPLAY=foo" and DISPLAY is picked up with a value of foo. But if I set "env TESTENV=foo" the variable TESTENV isn't even detected. – Geuis Dec 17 '11 at 11:53
  • That's strange. What version are you using and what OS? – Tom O'Connor Dec 17 '11 at 12:31
  • @Geuis Can you pastebin your upstart script? – Tom O'Connor Dec 17 '11 at 12:34
  • Hey Tom, I did figure that part out. I needed to add -E to sudo in order for it to pass the env vars through. Where I'm really stuck now is something slightly different. I'm trying to set a permanent environment variable that should be seen by Upstart or a shell session that I open myself. After much reading, its indicated this should go into /etc/environment. However, ever after I've done that and restart the server the variable TESTENV=foo isn't being seen. Do you have any thoughts on that? – Geuis Dec 17 '11 at 13:11
  • Here is the pastebin of the Upstart script, http://pastebin.com/tRj1e7kP – Geuis Dec 17 '11 at 13:14
  • Probably not recommended, but how about an export in /etc/rc.local ? – Tom O'Connor Dec 17 '11 at 13:32
  • @Geuis I'm also concerned by your use of sudo. From Upstart 1.4 onwards, you can use the setuid and setgid stanzas, so you could do setuid www-data and then exec, and it would run as www-data. See http://upstart.ubuntu.com/cookbook/#setgid – Tom O'Connor Dec 17 '11 at 13:39
  • 1
    I'll give rc.local a try after a bit of sleep. Thanks for the setgid tips. I've also been hesitant about sudo but that's what most of the examples I've seen do and it works. For my existing apps, its been working pretty reliably for a while now but I'm going to look into your link and see how it could be done more securely. Really appreciate your help tonight and hopefully I can figure out the rest. – Geuis Dec 17 '11 at 13:50
  • Upvote for sleep. No worries. – Tom O'Connor Dec 17 '11 at 13:50
1

I had the same problem. My startup script worked fine from the command line, but not from upstart script.

I simply had to source my . /home/username/.bashrc in my upstart script to get it working with all the correct environment variables.

script

  cd /home/me
  . /home/me/.bashrc

  ~/www/app/bin/server.production
end script
chovy
  • 320
  • 1
  • 4
  • 16
  • This does not work for me (Ubuntu Server 14.04.1). I get no error when sourcing /home//.bashrc inside the Upstart script, but the env vars don't stick around for the next command (the app/service being started). – odigity Jan 12 '15 at 00:29