Learn › Linux Foundations › Bash Shell Environment
.bash_profile - a hands-on Linux lab on a real virtual machine.
The startup file bash runs once at login. Why your aliases vanish over SSH, the sourcing block that pulls in ~/.bashrc, login versus non-login shells, and the precedence rule where the first of ~/.bash_profile, ~/.bash_login, ~/.profile wins and the rest are ignored.
You set up your shell exactly how you like it. In the last lessons you built aliases, you exported variables, you tuned ~/.bashrc so every terminal you open on the machine feels like home.
Then one day you connect to that same machine from far away, over SSH, and it is a stranger. Your aliases are gone. Your custom prompt is plain. The variables you exported are missing. Nothing you set up is there. You did not delete anything, and yet the shell that greets you when you sign in remotely has none of your settings.
This is one of the most common confusions in all of Linux, and it has a single, clean cause. The shell that greets you when you SIGN IN reads a different startup file. It is a different file from the one the shell you open on a running desktop reads. This lesson is about that first file: ~/.bash_profile.
The black boxes in this lesson are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. ~/.bash_profile is a personal file, so its exact lines differ from account to account. Where a box shows the contents of a real profile, the SHAPE is what matters; your own file's exact lines will differ, and that is noted each time.
~/.bash_profile is a startup script bash runs once, when you log in. The ~ is shorthand for your home directory, and the leading dot means the file is hidden, so a plain ls will not show it. It lives at the top of your home folder alongside ~/.bashrc.
Here is the whole idea in one sentence. ~/.bash_profile runs at LOGIN; ~/.bashrc runs for each new interactive terminal. Two files, two different moments. Remember from the .bashrc lesson that ~/.bashrc fires every time you open a fresh terminal window on a machine you are already sitting at. ~/.bash_profile is different: it fires once, at the moment you sign in.
The word for the shell you get when you sign in is a login shell. When you SSH into a machine, or type your username and password at a physical console, bash starts as a login shell and reads ~/.bash_profile. That is the setting that makes this file matter.
Before you read what is inside it, prove the file is there. Because its name starts with a dot it is hidden, so you need ls -a, the flag that shows hidden files, from the ls lesson. Look in your home directory now:
ls -a ~
prompt: student@linuxcamp:~$ answer: ls -a ~ output: . .. .bash_history .bash_logout .bash_profile .bashrc .profile hint: Use ls with the -a flag, which shows hidden dot files, pointed at your home directory: ls -a ~
There they are, the whole family of startup files, all hidden by the leading dot. .bashrc you already know. .bash_profile is the login file this lesson is about. And notice .profile is sitting right beside it. That third file is not decoration; it is part of a precedence rule you will meet in a moment. Your own home directory may list more files than this, but these dot files are the ones that shape your shell.
Now open the file and see what it actually does. On most systems ~/.bash_profile is short, and its main job is surprising: it reaches over and pulls in ~/.bashrc. Print it with cat, the file-printing command from the Reading Files module:
cat ~/.bash_profile
prompt: student@linuxcamp:~$ answer: cat ~/.bash_profile output:
if [ -f ~/.bashrc ]; then . ~/.bashrc fi hint: Use cat to print the file, giving it the path ~/.bash_profile: cat ~/.bash_profile
The exact lines in your ~/.bash_profile may differ, since every system and every account ships its own version. What is nearly universal is the BLOCK in the middle, the part that pulls in ~/.bashrc. That block is the point of the whole lesson, so read it closely next.
Look again at the three lines in the middle. In plain English they say: if a file called ~/.bashrc exists, run it now.
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
Two pieces are worth naming. [ -f ~/.bashrc ] is a test that asks does the file ~/.bashrc exist. And the lone dot, . ~/.bashrc, is the source command: it means run this file's lines inside my current shell, right here. A dot followed by a space and a filename is bash saying load that file's settings into me now.
So this tiny block is the bridge. It makes your login shell run ~/.bashrc on its way in, which means every alias and setting you put in ~/.bashrc reaches your login shell too. Both kinds of shell end up sharing the same config, and that is exactly what you want.
This block is the fix for the vanishing-aliases mystery from the top of the lesson. If ~/.bash_profile does NOT source ~/.bashrc, then a login shell (an SSH session) never runs ~/.bashrc, so your aliases and custom prompt are simply not loaded. They work in the terminals you open locally and vanish the instant you SSH in. The cure is one line: make ~/.bash_profile source ~/.bashrc.
Here is the whole distinction, side by side. There are two ways bash can start, and each reads a different file:
That single split explains the mystery. The terminal you open on a running desktop is a non-login shell, so it reads ~/.bashrc and your settings are all there. The shell you get over SSH is a login shell, so it reads ~/.bash_profile instead. Unless that file sources ~/.bashrc, your settings never load.
Because ~/.bash_profile runs exactly once per login, it is the natural home for setup that should happen a single time when you sign in: environment variables you want set for the whole session, starting an ssh-agent, or printing a login greeting. Per-terminal cosmetics like aliases belong in ~/.bashrc. That is why the standard pattern is to keep aliases in ~/.bashrc and have ~/.bash_profile source it.
You saw three files in your home directory earlier: ~/.bash_profile, ~/.profile, and there can also be ~/.bash_login. When bash starts as a login shell, it does NOT read all three. It reads the FIRST one that exists and then stops.
The order is fixed. Bash looks for these three files in this exact sequence:
The practical takeaway is sharp. If ~/.bash_profile exists, your ~/.profile is completely ignored at login, even though it is sitting right there in your home directory. People trip on this constantly. They add a setting to ~/.profile, log in, and nothing happens, because ~/.bash_profile won the race and stopped the search. (~/.profile gets its own lesson; the short version is that it is the older, more portable login file that other shells read too.)
This is why beginners are often told to put login settings in ~/.bash_profile specifically. Since it is first in the order, it is the file bash is guaranteed to read for a login shell when it exists, so nothing can quietly override it.
Scaffolding off. No command is printed this time. You have every piece you need.
You want to confirm, in one glance, that your login startup file really does hand off to ~/.bashrc. Print the contents of the file that a login shell reads first, so you can see the sourcing block with your own eyes.
prompt: student@linuxcamp:~$ answer: cat ~/.bash_profile output:
if [ -f ~/.bashrc ]; then . ~/.bashrc fi hint: The login shell reads ~/.bash_profile first. Print that file with cat: cat ~/.bash_profile
That is the everyday check. You printed ~/.bash_profile, the file a login shell reads first, and there is the block: if ~/.bashrc exists, source it. Seeing that block is how you confirm an SSH session will pick up your aliases. Your own file's comment line and exact spacing will differ from machine to machine, but the sourcing block is the piece that matters, and reading it for yourself is the habit a working engineer builds.
You earned this cheat sheet. Every row is something you just did or learned:
The one thing to carry out of here: put per-login setup in ~/.bash_profile, keep your aliases in ~/.bashrc, and have ~/.bash_profile source ~/.bashrc so both kinds of shell share your config.
When aliases go missing over SSH, do not go hunting through your whole setup. Just cat ~/.bash_profile and look for the . ~/.bashrc line. If it is not there, you found the bug in one command.
The practice terminal has shown you the shape of ~/.bash_profile. You found it with ls -a, read the sourcing block that saves your aliases, sorted login shells from non-login ones, and learned the precedence rule that lets one file quietly override another. Every one of those you typed yourself.
The Bash Environment module ends with one real Linux machine, the Bash Environment capstone mission, and that is where you work with these files for real. A VM boots just for you, with its own home directory and its own startup files. It hands you objectives that use exactly what you practiced across this module: variables, exports, aliases, the PATH, and the startup files that load them all when you sign in. One difference from here: the mission shows no commands. You read the objective, you recall the command, you type it. That recall is what makes it stick.
Finish the other Bash Environment lessons, then go tune a real login shell for yourself.
Practice .bash_profile in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.