Learn › Linux Foundations › Bash Shell Environment
.profile - a hands-on Linux lab on a real virtual machine.
Read the POSIX, shell-agnostic login file .profile: the banner that marks it a login file, the block that sources .bashrc only under bash, and the precedence rule that makes bash read .profile only when no .bash_profile or .bash_login exists. .profile contents vary by account, so the drills teach the structure you type (head, cat, grep, ls) and the precedence, not the exact file text.
Last lesson you met .bash_profile, the login file that only bash reads. Fair question: what happens if the shell running the login is NOT bash? Older servers, minimal containers, and the plain /bin/sh that scripts run under do not read .bash_profile at all. Something has to configure THEM at login too.
That something is ~/.profile. It is the shell-agnostic login file: the one place login setup can live so it works no matter which shell logs you in. It is also the file Debian and Ubuntu hand you by default, with no .bash_profile in sight. This lesson is about what is inside it, and the precedence rule that decides when bash reads it.
The black boxes below are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. The CONTENTS of a .profile differ from account to account, so every file shown here is the Debian default, kept as an example and marked so. On the real machine at the end of the module you read your own .profile.
~/.profile is your personal login startup file, written in POSIX shell syntax. POSIX is the portable standard that every Unix shell agrees on, so a POSIX script runs the same under bash, dash, sh, or ksh. That portability is the whole point of .profile.
Two ideas from earlier labs meet here. A login shell is the shell you get when you first sign in to a machine, as opposed to a fresh terminal tab opened on a desktop. And .bashrc, from Lesson 74, held your bash-only interactive tweaks: aliases, the prompt, shell options. Keep those two straight and .profile falls into place: it is for login-time environment setup that any shell should honor, while bash-only comforts stay in .bashrc.
Before you read a line of it, prove the file is really there and see its opening banner. head -1 prints just the first line of a file, and on the Debian default .profile that line is a fixed comment. Run it now:
head -1 ~/.profile
prompt: student@linuxcamp:~$ answer: head -1 ~/.profile output:
hint: Type head, a space, the number 1 with a dash in front, then the path: head -1 ~/.profile
That first line is a comment (it starts with #, so the shell ignores it) and it states the file's job in its own words: executed for login shells. Debian ships this exact banner. If your machine put a different first line there, that is fine; the banner is documentation, not behavior. What matters is the file exists and runs at login. Next you read the whole thing.
Now print the entire file with cat, the command you have used all through the course to dump a file to the screen. This is the form you will actually type when you want to see what your login does:
cat ~/.profile
prompt: student@linuxcamp:~$ answer: cat ~/.profile output:
if [ -n "$BASH_VERSION" ]; then if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" fi fi
if [ -d "$HOME/bin" ]; then PATH="$HOME/bin:$PATH" fi hint: Type cat, a space, then the path to the file: cat ~/.profile
That is the Debian default .profile. Your own file may have extra lines, or fewer, and the exact wording of the comments can differ. Do not memorize the text. Memorize the SHAPE: a block that sources .bashrc when the shell is bash, and a block that adds a folder to PATH. That shape is the lesson.
Look at the first if block from the output above. It is the single most important pattern in the file, and it explains how your aliases and prompt still load even though .profile is not a bash-only file:
if [ -n "$BASH_VERSION" ]; then
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Read it in plain English. $BASH_VERSION is a variable that bash sets and other shells do not, so [ -n "$BASH_VERSION" ] asks "am I running under bash?". If yes, and if a ~/.bashrc file exists, the line . "$HOME/.bashrc" runs it. That leading dot is the source command from Lesson 77's neighborhood: it reads another file into the current shell. So .profile handles the portable login setup, then, only when bash is the shell, pulls in .bashrc for the bash-only comforts. Grep for that dependency yourself:
grep bashrc ~/.profile
prompt: student@linuxcamp:~$ answer: grep bashrc ~/.profile output:
. "$HOME/.bashrc" hint: Type grep, a space, the word bashrc, a space, then the file: grep bashrc ~/.profile
Two lines matched: the comment that announces the intent, and the . "$HOME/.bashrc" line that does the work. This is why, on Debian, everything you put in .bashrc still shows up when you log in: the login runs .profile, and .profile sources .bashrc for you. Break that one line and a fresh login would stop loading your aliases. Your own file's exact indentation may differ, but if .profile mentions bashrc at all, this is the block it lives in.
Here is the idea that connects last lesson to this one, and the one people get wrong. When bash starts as a login shell, it does not read all three login files. It reads the FIRST one that exists, runs it, and stops:
First match wins, then bash stops looking. So ~/.profile is bash's login file ONLY when there is no ~/.bash_profile and no ~/.bash_login. That is exactly why Debian works the way it does: Debian ships no .bash_profile, so bash falls straight through to .profile. Prove which files exist on this machine with ls:
ls -la ~/.bash_profile ~/.profile
prompt: student@linuxcamp:~$ answer: ls -la ~/.bash_profile ~/.profile output: ls: cannot access '/home/student/.bash_profile': No such file or directory -rw-r--r-- 1 student student 807 Apr 1 09:14 /home/student/.profile
The dates, sizes, and username in that listing belong to the capture machine; yours will read differently. The MEANING is what stays true: .bash_profile is missing (the cannot access line), .profile is present. Because the first two files in the precedence table do not exist, bash uses .profile. If someone later creates a ~/.bash_profile, bash would read THAT instead and your .profile edits would silently stop affecting bash logins. That surprise is the number one .profile gotcha.
Scaffolding off. No command is printed this time. You have every piece you need.
You are on an unfamiliar Debian machine and you want to answer one question fast: does this account's .profile pull in .bashrc, or not? You do not want to read the whole file line by line. You want to search inside ~/.profile for the word bashrc and let the matching lines answer for you.
prompt: student@linuxcamp:~$ answer: grep bashrc ~/.profile output:
. "$HOME/.bashrc" hint: You want to search a file for a word. Think of the search command from the text-processing lessons, then the word bashrc, then the file ~/.profile.
That is the everyday move. grep searched inside ~/.profile for bashrc and printed every line that held it, so two matching lines told you at a glance: yes, this .profile sources .bashrc. No matches would have meant the chain is broken and bash-only settings would not load at login. You recalled grep <word> <file> from memory and pointed it at the right file, which is exactly the recall the real machine will ask of you.
Three things trip people up often enough to name.
The first is putting bash-only syntax in .profile. Because .profile can be read by plain sh or dash, a bash-only line like source ~/.bashrc (bash's spelled-out word for the dot) or a [[ ... ]] test can break a sh login with an error such as:
.profile: 12: source: not found
That means a non-bash shell hit a word it does not understand. What to check first: use only POSIX syntax in .profile. Write the portable dot, . ~/.bashrc, not source ~/.bashrc, and keep bash-only features out of this file.
The second is editing the wrong file. If a ~/.bash_profile exists, bash reads it and never touches .profile, so your careful .profile edits do nothing for bash logins and you are left puzzled. What to check first: run ls -la ~/.bash_profile ~/.profile and follow the precedence table. If .bash_profile is present, edit that, or have it source .profile.
The third is expecting .profile to run in a new terminal tab. It does not. .profile runs at LOGIN. A tab opened on a desktop is usually a non-login shell, which reads .bashrc and skips .profile entirely. What to check first: if a variable set in .profile is missing in a new tab, either set it in .bashrc, or make sure .bashrc inherits it through the login chain.
You earned this cheat sheet. Every row is a command you just ran, or a fact you just proved:
The one idea to carry out: .profile is the portable, any-shell login file, and on Debian it is the file bash actually uses because no .bash_profile sits ahead of it. Keep POSIX login setup here, keep bash-only comforts in .bashrc, and let the sources-bashrc block join the two.
If you ever WANT bash to have its own login file separate from the portable one, create ~/.bash_profile. The moment it exists, bash reads it first and ignores .profile. A common trick is to make that new .bash_profile a single line, . ~/.profile, so bash still runs the portable setup on purpose instead of by fallback.
The practice terminal has shown you the whole story of .profile. You confirmed the file with its login-shell banner, read the sources-bashrc block that ties it to your aliases, grepped to prove that link, and listed the login files to see the precedence for yourself. Every one of those you typed by hand.
The Bash Environment module ends with one real Linux machine, the Bash Environment capstone mission, and that is where you read a real .profile for yourself. A VM boots just for you, with its own login files and its own .bashrc chain. It hands you objectives that use exactly what you practiced across this module: variables, env, export, PATH, and the startup files that set them all at login. 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 read a real login file for yourself.
Practice .profile in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.