Environment
If you are working with the command line, you operate in an environment. For example, the command-line knows where your home folder is, where to find ruby, what's your username, and many other things. All this information is stored in environmental variables.
Environmental variables (or env vars, for short) describe the current terminal session. You can see them by typing "env".
Every line on this screen is a key/value pair, e.g.
HOME=/Users/bpourian
The HOME env variable defines where the home directory is for the current user. You can easily find variables responsible for setting the username, language, temporary directory, etc.
Every program you launch on your computer has access to the environment variables. They help the programs to understand what environment they are working in. For example, if you needed to create a temporary file in your Ruby code, you'd read the value of the TMPDIR env variable to find out where the temporary directory is.
You can view any single environment variable by typing "echo $ENV_VAR", e.g.
$ echo $HOME/Users/bpourian
echo
"echo" just prints whatever text you give it on the screen.
$ echo "Hello" Hello
It can be used to view environment variables as we've just seen.
It also can be used to save short strings to a file. Let's say you want to create a file with text "Hello, world".
echo "Hello, world" > hello.txt
This command will turn out to be useful on more than one occasion later.
PATH
One of the most important environment variables is PATH, so let's discuss it in detail. PATH is a colon-separated list of directories where the shell will be looking for the programs you ask it to run. On my computer it looks like this.
$ echo $PATH /Users/bpourian/.rvm/gems/ruby-2.0.0-p247/bin:/Users/bpourian/.rvm/gems/ruby-2.0.0-p247@global/bin:/Users/bpourian/.rvm/rubies/ruby-2.0.0-p247/bin:/Users/bpourian/.rvm/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
This is a list of paths, separated by colons. When you type a command without specifying its path, e.g. "ruby", the shell looks through all these directories until it finds this file and executes it. So, when you type "ls", the shell will be examining the following paths in order until it finds a file that exists.
/Users/shadchnev/.rvm/gems/ruby-2.0.0-p247/bin/ls /Users/bpourian/.rvm/gems/ruby-2.0.0- p247@global/bin/ls /Users/bpourian/.rvm/rubies/ruby-2.0.0-p247/bin/ls /Users/bpourian/.rvm/bin/ls /usr/bin/ls /bin/ls /usr/sbin/ls /sbin/ls /usr/local/bin/ls
On my system, "ls" will be found in "/bin/ls".
When we had to type "./hello.rb" to execute the file, instead of just "hello.rb"? This is because if we hadn't explicitely specified that the program was in the current directory, the shell would look in all PATH directories and wouldn't find it there. Every program that you can run from your command line without specifying where they are (ls, chmod, date, pwd, etc) are somewhere on the PATH.
You may have tried switching ruby versions on your machine using rvm. If not, you soon will be :-) How does it work? When you type
rvm use 1.9.3
rvm updates the PATH variable to include the folders relevant to the ruby version that you need. Then, when you type "ruby", the shell already knows where to look.
If you have installed some software but you can't run it (command not found error), double check that the PATH variable is set correctly.
Setting environment variables
To set environment variables:
export SEASON=winter
You've just created a new environment variable called SEASON. You can read its value back.
echo $SEASON
What if we wanted to modify PATH? Let's add one more directory at the end of PATH:
export PATH=$PATH:/Users/bpourian
This adds my home directory to the end of the list of paths in PATH.
Why would we want to modify environmental variables? One of the common use cases is storing sensitive data, e.g. passwords.
Let's say you're writing an open source project that uses photos from Facebook. Your code will need to use a secret key that will give you access to Facebook. This key is secret and you shouldn't share it with anyone. However, you want to share your open source code on Github. How should you do it?
Put your secret key in an environment variable and then read it from your code when you need it. For example:
export SECRET_KEY=12345abcde
Then, in your Ruby code, read the value:
secret_key = ENV['SECRET_KEY']
This way you'll be able to share your code with anyone without compromising your keys.
Profile files
The environment variables don't last for long. After you set them, they only stay in the environment until the end of the current shell session. However, you normally want them being available in all new shell sessions as well. Profile files are often used to achieve this.
Let's create (or re-create if it already exists) the env variable SEASON.
export SEASON=winter
Verify that it exists.
$ echo $SEASON winter
Now open another terminal window and try to see if the variable exist. It shouldn't: it only exists in the shell where it was originally created. Every variable should be recreated every time a new terminal session starts.
Every time a new shell session starts, several files are executed automatically on load. They are used, among other things, to configure the environment. One of these files is called .bash_profile (note the dot at the beginning). It is located in the home directory.
If you have RVM installed (as you should), there will be some code related to loading RVM into the shell. This code makes RVM available for you to use in every shell.
We can also use the same file to create "permanent" env vars. Let's put our SEASON variable into the file.
echo "export SEASON=winter" >> ~/.bash_profile
(Double angle bracket means append, while single angle bracket means overwrite)
Now our .bash_profile file looks like this:
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function* export SEASON=winter
Now open a new shell window and verify that the variable exists. If you've done everything correctly, it will.