centos etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
centos etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

1 Nisan 2014 Salı

Shell Types and Shell Config Files: /etc/profile, /etc/bashrc, ~/.bash_profile, ~/.bashrc

Setting JAVA_HOME must be easy, right? However, this can sometimes get tricky. To better understand your version of "JAVA_HOME is not set" errors, it can be instructive to look at shell types, config files and their working principles. 

I am using Centos 6.5. Below explanations should also work for Red Hat implementations. In other Linux implementations, it could differ.


1. Environment Variables 

1.1. Process Locality

If you open two shells and define an environment variable in first shell, second shell will not be able to see new environment variable.

1. Open two terminals
2. Create an environment variable in first:
> export SHELLNUMBER=1

3. In second shell, type:
> echo $SHELLNUMBER
This will print nothing.

1.2. Inheritance

If you define a variable in a shell and open a sub-shell, new variable will be available to sub-shell.
1. Open a terminal
2. Create an environment variable:
> export PARENT=1
3. Create a sub-shell by typing:
> bash
4. List variables:
> env | grep PARENT
This will print 
PARENT=1

We can continue as follows to also test process locality:
5. Create another variable in sub-shell and list variables:
> export PARENT2=2
> env | grep PARENT
This will print:
PARENT=1
PARENT2=2
6. Now exit sub-shell and list variables:
> exit
> env | grep PARENT
This will print only
PARENT=1

As you can see, variables defined in sub-shell are not available to parent shell.

1.3. Case-Sensitivity

Environment variables are case sensitive meaning that JAVA_HOME and Java_Home are different variables. It is a common practice to use capital letters and underscore signs.

2. Shell Types

We can group shells in two categories: interactive/non-interactive and login/non-login shells. 


2.1. Interactive/non-interactive shells

An interactive shell is the one whose input and output are connected to terminals or the one started with -i flag. 
Non-interactive shell is the one where user input is not needed such as shell scripts.

You can learn if the shell you are working (probably interactive) by typing:
> echo $-
If output contains i, it is interactive.

To see a non interactive shell, create a shell script name test.sh with contents:
echo $-
Then run with:
> bash test.sh
The output will not contain i.

2.2. Login and non-login shells

A login shell is the shell when you login or the one started with -l flag.
In login shells, it usually prompts for user and password. This is the case when you ssh to remotely login to a linux machine.
Other Examples:
> bash -l

> su -l 

In non-login shells, it does not prompt for user and password. This is the case when you are already logged in and type /bin/bash. An interactive non-login shell is also started when you open a terminal in a graphical environment.

3. Config Files

Files under /etc is usually provide global settings and files under user home directory provides user specific settings. User specific files can override global settings.

An interactive login shell reads /etc/profile and ~/.bash_profile. In Centos, ~/.bash_profile also reads ~/.bashrc and then /etc/bashrc files.

An interactive non-login shell gets its parent environment and reads ~/.bashrc and /etc/bashrc for additional configuration.

A non-interactive non-login shell  expands $BASH_ENV variable if not null and reads specified file. Otherwise, it only gets its parent environment.

You can test this behaviour as following:
1. Open a terminal. We will use this as our main shell, do not close it.
2. Create a shell script named test.sh with contents:
env | grep SCRIPTVAR 

3. Define a new variable in /etc/bashrc file:
export SCRIPTVAR=1 
This variable is not be available to our main shell since /etc/bashrc must be read again.

4. Will it be available to shell script? Run test.sh:
> bash test.sh
This will not print our new variable

5. Set BASH_ENV variable to /etc/bashrc (just for testing, not for daily usage):
> export BASH_ENV=/etc/bashrc

6. Run script again and it prints SCRIPTVAR=1. 













31 Mart 2014 Pazartesi

Setting Environment Variables On Linux

You can set environment variables in Linux by export command. 

In this post, I will set JAVA_HOME and M2_HOME. 

I am using Centos 6.5. Below explanations should also work for Red Hat implementations. In other Linux implementations, it could differ.


1. export Command

1.1. Define variable

This defines JAVA_HOME variable:
> export JAVA_HOME=/usr/lib/jvm/jdk-1.7.0

You can see your new variable by typing:

> echo $JAVA_HOME

When assigning a value to a variable, do not use $ (dollar) sign.

When assigning a value to a variable, do not leave spaces between = (equals) sign.


1.2. You can append to PATH variable

To use your executables without typing the full path, you can append your environment variables to PATH variable:
export JAVA_HOME=/usr/lib/jvm/jdk-1.7.0
export PATH=$PATH:$JAVA_HOME/bin


1.3. You can assign/append multiple variables:

> export JAVA_HOME=/usr/lib/jvm/jdk-1.7.0
> export M2_HOME=/usr/local/apache-maven/apache-maven-3.0.4
> export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin

export command can be run from command line or can be put inside a shell script.



2. Running from Command Line

If you define new environment variables from command line, these variables will only be available to current shell session and its sub sessions. 

This implies that:

1. If you define a variable in a shell and exit later on ( for example by typing exit or closing the shell window), defined variables will be lost.
2. If you open two shell windows and define a variable in first shell, the second shell will not be aware of new variable. It will only be available to first session.
3. If you define a variable in a shell window and open a child shell (for example by typing bash), this new variable will also be available in child shell session.

So we must put our environment variables in specific files to make them permanent.



3. Permanent Environment Variables

To make an environment variable permanent, export commands must be placed in specific files.
When a shell is started, it reads a collection of startup files to help create an environment. By assigning environment variables in these files, every shell will read these variables.


3.1. System-wide Environment Variables

The recommended way is creating a shell script under /etc/profile.d and putting your export commands inside this script. 

Follow these steps:

    1. Create a shell script named environmentvariables.sh under /etc/profile.d

    2. Write:

export JAVA_HOME=/usr/lib/jvm/jdk-1.7.0
export M2_HOME=/usr/local/apache-maven/apache-maven-3.0.4
export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin

    3. After creating this file, re-login to your account for a clear environment creation.This change will be system-wide.


environmentvariables.sh will be read by /etc/profile when a new login shell is started. You can get a new login shell by re-logging in your computer or refreshing your ssh connection.



3.1.1. Other Files

Another file that can be used to put environment variables is /etc/bashrc

In my tests, this file is read whenever a new shell is started. However, since there are condition checks in this file, it will be effective when a non-login interactive shell is started. Opening a new terminal or typing "bash" will start a new non-login interactive shell.


This file also reads scripts under /etc/profile.d, if the shell is non-login interactive shell. This also suggests that rather than modifying /etc/bashrc, you should put your export commands into scripts under /etc/profile.d. 



3.2. User Specific Environment Variables

The recommended way is assigning environment variables inside the ~/.bash_profile file which is user specific version of /etc/profile. Changes to this file will be read, when a new login shell is started for a specific user.

After modifying this file, re-login to your account or refresh your shh connection.



3.2.1. Other Files

~/.bashrc is often suggested to put environment variables for user specific behaviour.

For detailed discussion of shell types and their configuration files, you can read my next post.