Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby, Unicorn, and environment variables

While playing with Heroku, I found their approach of using environment variables for server-local configuration brilliant. Now, while setting up an application server of my own, I find myself wondering how hard that would be to replicate.

I'm deploying a sinatra application, riding Unicorn and Nginx. I know nginx doesn't like to play with the environment, so that one's out. I can probably put the vars somewhere in the unicorn config file, but since that's under version control with the rest of the app, it sort of defeats the purpose of having the configuration sit in the server environment. There is no reason not to keep my app-specific configuration files together with the rest of the app, as far as I'm concerned.

The third, and last (to my knowledge) option, is setting them in the spawning shell. That's where I got lost. I know that login and non-login shells use different rc files, and I'm not sure whether calling something with sudo -u http stuff is or not spawning a login shell. I did some homework, and asked google and man, but I'm still not entirely sure on how to approach it. Maybe I'm just being dumb... either way, I'd really appreciate it if someone could shed some light on the whole shell environment deal.

like image 314
mkaito Avatar asked Apr 29 '11 20:04

mkaito


People also ask

How do I pass an environment variable in Ruby?

To pass environment variables to Ruby, simply set that environment variable in the shell. This varies slightly between operating systems, but the concepts remain the same. To set an environment variable on the Windows command prompt, use the set command.

Where are Ruby environment variables stored?

You can find a list of ALL your environment variables with the env command in Linux / Mac & the set command in Windows. Example: PWD=/home/jesus SHELL=/usr/bin/zsh RUBY_ENGINE=ruby RUBY_VERSION=2.6. 0 GEM_ROOT=/opt/rubies/ruby-2.6.

What is ENV in Ruby?

The ENV class stands for environment variables. Environment variables store secrets, variables, or configurations in our application that we don't want the public to know. They could be a database URL, API keys, etc. The form of an environment variable is a key/value or a name/value pair.


2 Answers

I think your third possibility is on the right track. What you're missing is the idea of a wrapper script, whose only function is to set the environment and then call the main program with whatever options are required.

To make a wrapper script that can function as a control script (if prodEnv use DB=ProdDB, etc), there is one more piece that simplifies this problem. Bash/ksh both support a feature called sourcing files. This an operation that the shell provides, to open a file and execute what is in the file, just as if it was in-lined in the main script. Like #include in C and other languages.

ksh and bash will automatically source /etc/profile, /var/etc/profile.local (sometimes), $HOME/.profile. There are other filenames that will also get picked up, but in this case, you'll need to make your own env file and the explicitly load it.

As we're talking about wrapper-scripts, and you want to manage how your environment gets set up, you'll want to do the sourcing inside the wrapper script.

How do you source an environment file?

envFile=/path/to/my/envFile  
. $envFile

where envFile will be filled with statements like

dbServer=DevDBServer
webServer=QAWebServer
....

you may discover that you need to export these variable for them to be visble

export dbServer webServer

An alternate assignment/export is supported

export dbServer=DevDBServer
export webServer=QAWebServer

Depending on how non-identical your different environments are, you can have your wrapper script figure out which environment file to load.

case $( /bin/hostame ) in
 prodServerName )
     envFile=/path/2/prod/envFile ;;
 QASeverName )
     envFile=/path/2/qa/envFile ;;
 devSeverName )
     envFile=/path/2/dev/envFile ;;
esac

. ${envFile}

#NOW call your program
myProgram -v -f inFile -o outFile ......

As you develop more and more scripts in your data processing environment, you can alway source your envFile at the top. When you eventually change the physical location of a server (or it's name), then you have only one place that you need to make the change.

IHTH

like image 80
shellter Avatar answered Oct 09 '22 10:10

shellter


Also a couple of gems dealing with this. figaro that works both with or without heroku. Figaro uses a yaml file (in config and git ignored) to keep track of variables. Another option is dotenv that reads variables from an .env file. And also another article with all them options.

like image 24
froderik Avatar answered Oct 09 '22 11:10

froderik