Processes Have an Environment

Environment, in this sense, refers to what’s known as ‘environment variables’. Environment variables are key-value pairs that hold data for a process.

Every process inherits environment variables from its parent. They are set by a parent process and inherited by its child processes. Environment variables are per-process and are global to each process.

Here’s a simple example of setting an environment variable in a bash shell, launching a Ruby process, and reading that environment variable.

$ MESSAGE='wing it' ruby -e "puts ENV['MESSAGE']"

The VAR=value syntax is the bash way of setting environment variables. The same thing can be accomplished in Ruby using the ENV constant.

# The same thing, with places reversed!
ENV['MESSAGE'] = 'wing it'
system "echo $MESSAGE"

Both of these examples print:

wing it

In bash environment variables are accessed using the syntax: $VAR. As you can tell from these few examples environment variables can be used to share state between processes running different languages, bash and ruby in this case.

It’s a hash, right?

Although ENV uses the hash-style accessor API it’s not actually a Hash. For instance, it implements Enumerable and some of the Hash API, but not all of it. Key methods like merge are not implemented. So you can do things like ENV.has_key?, but don’t count on all hash operations working.

puts ENV['EDITOR']
puts ENV.has_key?('PATH')
puts ENV.is_a?(Hash)

outputs:

vim
true
false

In the Real World

In the real world environment variables have many uses. Here’s a few that are common workflows in the Ruby community:

$ RAILS_ENV=production rails server
$ EDITOR=mate bundle open actionpack
$ QUEUE=default rake resque:work

Environment variables are often used as a generic way to accept input into a command-line program. Any terminal (on Unix or Windows) already supports them and most programmers are familiar with them. Using environment variables is often less overhead than explicitly parsing command line options.

System Calls

There are no system calls for directly manipulating environment variables, but the C library functions setenv(3) and getenv(3) do the brunt of the work. Also have a look at environ(7) for an overview.