Shell Startup#
When you login to a linux-based machine you interact with the operating system via a program called a shell. There are various types of shell programs. One of the more common is bash. Bash is the default shell on NREL's HPC platforms. This document describes ways you can customize your shell's in particular, bash's behavior.
Getting Started#
When you have a window open attached to a platform, you are actually running a program on the remote computer called a shell. There are various types of shell programs. One of the more common is bash.
The shell program provides your link to the machine's operating system (OS). It is the interface between a user and the computer. It controls the computer and provides output to the user. There are various types of interfaces but here we discuss the command-line interface. That is, you type commands and the computer responds.
What happens on login#
When you login to a machine, you are put in your home directory. You can see this by running the command pwd. Run the command ls -a to get a listing of the files. The -a option for the ls commands enables it to show files that are normally hidden. You'll see two important files that are used for setting up your environment.
- .bash_profile
- .bashrc
These files are added to your home directory when your account is created.
When you login, the file .bash_profile is sourced (run) to set up your environment. The environment includes settings for important variables, command aliases, and functions.
Here is the default version of .bash_profile:
[nreluser@kl2 ~] CPU $ cat ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
Notice the lines:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
The "if" statement says that if you have a file .bashrc in your home directory, then run it. The . by itself is shorthand for "source" and ~/ is shorthand for your home directory.
Now, let's look at the default ~/.bashrc file:
[nreluser@kl2 ~] CPU $ cat ~/.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
then
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
First, you will see that this runs the system's version of the bashrc from /etc/; the purpose is to initialize system-wide functions and aliases.
Second, note that it sets up the user specific environment by updating the PATH environment variable. The PATH environment variable contains the file directory paths a computer will look for commands to run. You can append or, like in this case, prepend directories to it; the PATH is set to $HOME/.local/bin:$HOME/bin:$PATH
, $HOME
being another environment variable that points to your home directory. This adds the user's commands to the PATH if those commands are in either $HOME/.local/bin
or $HOME/bin
.
Note in both of these files we have a place where you are encouraged to add user defined aliases and functions. You can also set environmental variables, such as PATH and a related variable LD_LIBRARY_PATH. You may want to load modules which also set environmental variables.
Suggestions (Philosophy)#
We're going to discuss customizing your environment. This is done by editing these two files. Before we do that here are three suggestions:
- If you are new to linux use the nano editor
- Make a backup of your current versions of the two files
- Make additions in external files
Nano is an easy to learn and use text editor. The official web page for nano is https://www.nano-editor.org. There are many online tutorials. There are other editors available, but nano is a good starting point.
It is very easy to make mistakes when doing edits or you just might want to go back to a previous version. So back it up. Here are commands to do so:
[hpcuser2@eyas1 ~]$ NOW=`date +"%y%m%d%H%M"`
[hpcuser2@eyas1 ~]$ echo $NOW
2303221513
[hpcuser2@eyas1 ~]$ cp .bashrc bashrc.$NOW
[hpcuser2@eyas1 ~]$ cp .bash_profile bash_profile.$NOW
[hpcuser2@eyas1 ~]$ ls *2303221513
bash_profile.2303221513 bashrc.2303221513
[hpcuser2@eyas1 ~]$
In most cases, you won't need to edit both .bashrc and .bash_profile. Since running .bash_profile runs .bashrc you can usually just edit .bashrc. (See the section Difference between login and interactive shells which describes cases where .bashrc is run even if .bash_profile is not.)
Instead of adding a bunch of text to .bashrc, make your additions in an external file(s) and just source the file(s) inside of .bashrc. Then, you can "turn off" additions by just commenting out the source lines. Also, you can test additions by sourcing the file from the command lines.
Additions#
The most common additions to your environment fall into these categories:
- Setting variables
- Creating Aliases
- Loading modules
- Adding Functions
We'll discuss each. We're going to assume that you created a directory ~/MYENV and in that directory you have the files:
- myvars
- myaliases
- mymods
- myfuncs
Then, to enable all of your additions you can add the following lines to your .bashrc file:
if [ -f ~/MYENV/myvars ]; then . ~/MYENV/myvars ; fi
if [ -f ~/MYENV/myaliases ]; then . ~/MYENV/myaliases ; fi
if [ -f ~/MYENV/mymods ]; then . ~/MYENV/mymods ; fi
if [ -f ~/MYENV/myfuncs ]; then . ~/MYENV/myfuncs ; fi
Note the additions will not take effect until you logout/login or until you run the command source ~/.bashrc Before going through the logout/login process, you should test your additions by manually running these commands in the terminal window.
Setting variables#
We have discussed the PATH variable. It points to directories which contain programs. If you have an application that you built, such as myapp in /projects/mystuff/apps, you can add the line
export PATH=/projects/mystuff/apps:$PATH
to your ~/MYENV/myvars file. Then when you login, the system will be able to find your application. The directories in path variables are seperated by a ":". If you forget to add $PATH to the export line the new PATH variable will be truncated and you will not see many "system" commands.
Another important variable is LD_LIBRARY_PATH. This points to directories containing libraries your applications need that are not "bundled" with your code. Assuming the libraries are in projects/mystuff/lib, you would add the following line:
export LD_LIBRARY_PATH=/projects/mystuff/lib:$LD_LIBRARY_PATH
If you have a commercial application that requires a license server you may need to set a variable to point to it. For example:
export LSERVER=license-1.hpc.nrel.gov:4691
Creating aliases#
Aliases are command shortcuts. If there is a complicated command that you often use, you might want to crate an alias for it. You can get a list of aliases defined for you by just running the command alias. The syntax for an alias is:
alias NAME="what you want to do"
#Show my running and queued jobs in useful format
alias sq='squeue -u $USER --format='\''%10A%15l%15L%6D%20S%15P%15r%20V%N'\'''
#Kill all my running and queued jobs
alias killjobs="scancel -u $USER"
#Get a list of available modules
alias ma='module avail'
#Get the "source" for a git repository
alias git-home='git remote show origin'
#Get a compact list of loaded modules
alias mlist='module list 2>&1 | egrep -v "Current|No modules loaded" | sed "s/..)//g"'
Loading modules#
Most HPC platforms run module systems. When you load a module, it will change some environmental variable settings. Often, PATH and LD_LIBARAY_PATH are changed. In general, loading a module will allow you to use a particular application or library.
If you always want gcc version 12 and python 3.10 in you path, you could add the following to your ~/MYENV/mymods file:
module load gcc/12.1.0
module load python/3.10.2
Running the command module avail will show the modules installed on the system.
If you have modules that you created, you can make them available to the load command by adding a command like the following in your ~/MYENV/mymods file:
module use /projects/mystuff/mods
The "module use" command needs to be before any module load command that loads your coustom modules.
Adding functions#
Functions are like aliases but generally multiline and more complex. You can run the command **compgen -A function ** to see a list of defined functions. Here are a few functions you might want to add to your environment:
# given a name of a function or alias show its definition
func ()
{
typeset -f $1 || alias $1
}
# find files in a directory that changed today
today ()
{
local now=`date +"%Y-%m-%d"`;
if (( $# > 0 )); then
if [[ $1 == "-f" ]]; then
find . -type f -newermt $now;
fi;
if [[ $1 == "-d" ]]; then
find . -type d -newermt $now;
fi;
else
find . -newermt $now;
fi
}
Most people who have worked in HPC for some time have collected many functions and alias they would be willing to share with you.
If you have a number of files in your ~/MYENV directory you want sourced at startup, you can replace the set of 4 "if" lines shown above with a "for list" statement. The following will source every file in the directory. It will not source files in subdirectories within ~/MYENV. If you want to temporarly turn off additions, you can put them in a subdirectory ~/MYENV/OFF. The find command shown here will return a list of files in the directory but not subdirectories. Again, recall that the changes will not be in effect until you logout/login.
for x in `find ~/MYENV -type f` ; do
source $x
done
Difference between login and interactive shells#
This section is based in part on Stack Overflow question What are the differences between a login shell and interactive shell?
The shell that gets started when you open a window on a HPC is called a login shell. It is also an interactive shell in that you are using it to interact with the computer. Bash can also be run as a command. That is, if you enter bash as a command you will start a new instance of the bash shell. This new shell is an interactive shell but not a login shell because it was not used to do the login to the platform.
When you start a new interactive shell the file .bashrc is sourced. When you start a login shell the file .bash_profile is sourced. However, most versions of .bash_profile have a line that will also source .bashrc.
When you submit a slurm batch job with the command sbatch neither of the two files .bashrc or .bash_profile are sourced. Note that, by default, the environment you have set up at the time you run sbatch is passed to the job.
When you start a slurm interactive session, for example, using the command
salloc --nodes=1 --time=01:00:00 --account=$MYACCOUNT --partition=debug
the file .bashrc is sourced.
Troubleshooting#
The most common issue when modifying your environment is forgetting to add the previous version of PATH when you set a new one. For example,
Do this:
export PATH=/projects/myapps:$PATH
Don't do this:
export PATH=/projects/myapps
If you do the second command you will lose access to most commands and you'll need to logout/login to restore access.
Always test additions before actually implementing them. If you use the files in ~/MYENV to modify your environment manually run the commands
if [ -f ~/MYENV/myvars ]; then . ~/MYENV/myvars ; fi
if [ -f ~/MYENV/myaliases ]; then . ~/MYENV/myaliases ; fi
if [ -f ~/MYENV/mymods ]; then . ~/MYENV/mymods ; fi
if [ -f ~/MYENV/myfuncs ]; then . ~/MYENV/myfuncs ; fi
to test things. After they are working as desired then add these lines to your .bashrc file. You can add a # to the lines in your .bashrc file to disable them.
There are copies of the default .bashrc and .bash_profile files in
- /etc/skel/.bash_profile
- /etc/skel/.bashrc
Some commands#
Command | Explanation |
---|---|
man |
Print manual or get help for a command. Examples:
|
ls |
List directory contents. Note:
|
echo |
Prints text to the terminal window |
mkdir |
Creates a directory |
pwd |
Prints working directory; that is, gives the name of the directory you are currently in. |
cd |
Changes directory. Note:
|
mv |
Moves or renames a file or directory |
nano |
Opens a simple text editor. See above. |
rm |
Removes a file. Note:
rm -rf ~ as this will completely delete your home directory. |
rmdir |
Removes an empty directory. It's safer than rm -rf |
less |
Views the contents of a text file |
> |
Redirects output from a command to a file. Example:
|
> /dev/null |
A special case of > suppress normal output by sending it the the "null file" |
2> err 1> out |
Sends errors from a command to the file err and normal output to out. Note:
|
>> |
similar to > but appends to the file |
cat |
Read a file and send output to the terminal. Note:
|
sort |
Outputs a sorted version of a file |
| |
A pipe takes the standard output of one command and passes it as the input to another. Example:
|
head |
Shows the start of a file |
tail |
Shows the end of a file |
which |
Shows the location of a command. Of note, you cannot use which with builtin shell commands. |
exit |
Exits out of a shell. Can be used to logout. |
logout |
Logs out of a shell. |
grep |
Searches for a string in output or file(s) |
history |
Displays the command history |
source |
Read and execute commands from a script and executes it in the current shell. Note:
|
find |
Locates files/directories with particular characteristics; a very useful command. Examples:
|
compgen |
Shows various sets of commands. Examples:
|