| |

LFCS 6 ๐Ÿง The Shell โ€” How It Works

The shell is the interface between the user and the kernel. Every command typed at a terminal is read, parsed, expanded, and executed by the shell. The LFCS exam is taken in a shell, and nearly every task on the exam is performed by typing commands into it. Understanding what the shell does with those commandsโ€”how it interprets them, expands them, and hands them to the kernelโ€”is the foundation for everything else.

This chapter covers the shell’s operation: the interactive loop, the command execution path, the environment, the startup files, and the features that the exam relies on. You will learn what happens between pressing Enter and seeing output, how the shell finds the program to run, how the environment and variables work, and how the shell’s configuration files are loaded.

Key point: The shell is a program, not part of the kernel. It reads a line, performs expansions, resolves the command to a file, forks a child process, executes the command in the child, waits for it to finish, and prints the prompt again. The environment is a set of name-value pairs passed to every child process. Variables that are exported become part of the environment; variables that are not exported are shell-local.


Why understanding the shell matters

The exam problem. The LFCS is performance-based. Every task is performed in a shell. If the shell does not behave as expected, the task fails. A PATH that does not include a directory, a variable that is not exported, a startup file that overrides a settingโ€”these are shell-level problems that look like command-level problems.

The debugging problem. When a command “does not work,” the failure is often in the shell’s parsing, not in the command itself. A glob that expands to the wrong files, a variable that expands to an empty string, a quote that is missingโ€”these are shell issues. Understanding the shell’s expansion order is understanding where to look.

The configuration problem. The shell reads configuration files at login and at startup. Which files are read depends on whether the shell is a login shell or an interactive shell, and whether it is bash or zsh. The LFCS includes tasks that require setting an environment variable persistently, and the answer depends on which file the shell reads.

The scripting problem. Every shell command is a mini-program. A script combines them. The shell’s exit codes, conditionals, loops, and functions are the building blocks of the scripts that the exam expects you to read and write.

The environment problem. The environment is the set of variables that programs inherit. PATH, HOME, USER, LANG, EDITORโ€”these are read by programs to determine their behavior. Setting them correctly, and persisting the settings, is a routine task.


a. The shell’s execution loop

The shell is a loop: read, parse, expand, execute, wait, repeat.

$ ls -l /etc/hosts
-rw-r--r-- 1 root root 221 Oct 8 10:00 /etc/hosts
$

When the user types ls -l /etc/hosts and presses Enter:

  1. The shell reads the line from the terminal.
  2. It tokenizes the line into words: ls, -l, /etc/hosts.
  3. It performs expansions: no variables, no globs, no command substitution.
  4. It resolves the command: ls is found in a directory in PATH.
  5. It forks a child process.
  6. The child executes /bin/ls with the arguments -l and /etc/hosts.
  7. The parent waits for the child to exit.
  8. The shell prints the prompt again.

The ls command is an external program. Some commands are built into the shellโ€”cd, echo, export, read, set. They are executed by the shell itself because they affect the shell’s state. An external program runs in a child process and cannot change the parent’s state.

$ cd /tmp
$ pwd
/tmp

The cd command is a built-in. If it were an external program, it would change the child’s directory and exit, leaving the parent’s directory unchanged. The built-in runs in the shell, so the change persists.

To see whether a command is a built-in, use type.

$ type cd
cd is a shell builtin
$ type ls
ls is /usr/bin/ls
$ type -a echo
echo is a shell builtin
echo is /usr/bin/echo

The type -a shows all the places a command is found. The shell checks built-ins first, then functions, then aliases, then PATH.

The PATH variable is a colon-separated list of directories. The shell searches them in order when it does not find the command as a built-in.

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

The first matching executable is the one that runs. To see which file would run, use which.

$ which ls
/usr/bin/ls
$ which python3
/usr/bin/python3

The which command searches PATH and prints the first match. It does not check built-ins or aliases. Use type for the full picture.


b. Variables, the environment, and export

A shell variable is a name-value pair. It is created by assignment.

$ name="Alice"
$ echo "$name"
Alice

The variable name holds the string Alice. The $name is expanded by the shell before the echo command runs. The echo command receives the string Alice as its argument, not the variable name.

The distinction between a shell variable and an environment variable is export. A shell variable is local to the shell. An environment variable is passed to every child process.

$ name="Alice"
$ bash -c 'echo $name'      # empty, not exported
$ export name
$ bash -c 'echo $name'      # Alice

The bash -c runs a child shell. The child inherits the environment, not the shell’s local variables. The export promotes the variable to the environment, so the child sees it.

The env command prints the environment.

$ env
SHELL=/bin/bash
USER=alice
HOME=/home/alice
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
...

The env command runs a program with a modified environment. It is used in scripts to set variables for a single command.

$ env EDITOR=vim git commit

The EDITOR variable is set for the git commit command only. It does not affect the current shell.

To unset a variable, use unset.

$ unset name
$ echo "$name"

The variable is removed. The echo prints an empty line.

To see the value of a variable with a default, use ${var:-default}.

$ echo "${name:-Bob}"
Bob
$ name="Alice"
$ echo "${name:-Bob}"
Alice

The ${name:-Bob} expands to the value of name if it is set and non-empty, and to Bob otherwise. The ${name:=Bob} assigns the default if the variable is unset. The ${name:?error} prints an error and exits if the variable is unset.

The shell has special variables. $? is the exit code of the last command. $$ is the PID of the shell. $! is the PID of the last background process. $0 is the name of the script. $1, $2, … are the positional parameters. $# is the number of positional parameters. $@ and $* are all the positional parameters.

$ ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
$ echo $?
2

The exit code is 2, which indicates an error. The convention is that 0 means success and any non-zero value means failure.

$ true
$ echo $?
0
$ false
$ echo $?
1

The true command always exits 0. The false command always exits 1.


c. Shell startup files and options

The shell reads configuration files when it starts. Which files are read depends on the shell and how it is invoked.

For bash:

Shell typeFiles read
Login shell/etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile
Interactive non-login/etc/bash.bashrc, ~/.bashrc
Non-interactiveThe file named by BASH_ENV

A login shell is started when the user logs inโ€”at the console, over SSH, or with bash --login. It reads the profile files. A non-login interactive shell is started when a terminal is opened in a graphical session or when bash is run without --login. It reads the bashrc files. A non-interactive shell is used to run a script. It reads neither, unless BASH_ENV is set.

For zsh, the files are /etc/zsh/zshenv, ~/.zshenv, /etc/zsh/zprofile, ~/.zprofile, /etc/zsh/zshrc, ~/.zshrc, /etc/zsh/zlogin, ~/.zlogin. The order is different, and the files serve different purposes. ~/.zshenv is read for every shell. ~/.zshrc is read for interactive shells.

The LFCS uses bash on both Ubuntu and CentOS. The startup files that matter for persistence are ~/.bashrc and ~/.bash_profile.

# ~/.bashrc
export EDITOR=vim
alias ll='ls -la'

The ~/.bashrc is read by interactive non-login shells. On Ubuntu, ~/.bash_profile sources ~/.bashrc if it exists. On CentOS, the same pattern is common. The result is that ~/.bashrc is read in most interactive contexts.

To make an environment variable available to all processes, it must be exported and set in a file that the shell reads. For a single user, ~/.bashrc or ~/.bash_profile. For all users, /etc/profile or /etc/profile.d/*.sh.

# /etc/profile.d/custom.sh
export EDITOR=vim

The /etc/profile.d/ directory contains scripts that are sourced by /etc/profile. This is the standard way to set system-wide environment variables.

Shell options change the shell’s behavior. The set command lists and sets them.

$ set -o
allexport       off
braceexpand     on
emacs           on
errexit         off
...

The set -e enables errexit, which causes the shell to exit when a command fails. The set -u treats unset variables as an error. The set -x prints each command before executing it, which is useful for debugging scripts. The set -o pipefail makes a pipeline fail if any command in it fails.

#!/bin/bash
set -euo pipefail

The shebang line and set -euo pipefail are the standard preamble for a robust bash script. They cause the script to exit on error, treat unset variables as errors, and fail pipelines when any command fails.


Complete Example Session

# ============================================
# PART 1: SHELL EXECUTION
# ============================================
$ ls -l /etc/hosts
$ type ls
ls is /usr/bin/ls
$ type cd
cd is a shell builtin
$ which ls
/usr/bin/ls
# ============================================
# PART 2: PATH
# ============================================
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ PATH="$HOME/bin:$PATH"
$ export PATH
# ============================================
# PART 3: VARIABLES
# ============================================
$ name="Alice"
$ echo "$name"
Alice
$ unset name
$ echo "$name"
# ============================================
# PART 4: EXPORT
# ============================================
$ name="Alice"
$ bash -c 'echo $name'

$ export name
$ bash -c 'echo $name'
Alice
# ============================================
# PART 5: SPECIAL VARIABLES
# ============================================
$ echo $?
0
$ echo $$
12345
$ echo $HOME
/home/alice
# ============================================
# PART 6: EXIT CODES
# ============================================
$ true
$ echo $?
0
$ false
$ echo $?
1
$ ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
$ echo $?
2
# ============================================
# PART 7: DEFAULT VALUES
# ============================================
$ echo "${name:-Bob}"
Bob
$ name="Alice"
$ echo "${name:-Bob}"
Alice
# ============================================
# PART 8: STARTUP FILES
# ============================================
$ cat ~/.bashrc
export EDITOR=vim
alias ll='ls -la'
$ source ~/.bashrc
$ echo $EDITOR
vim
# ============================================
# PART 9: SYSTEM-WIDE ENVIRONMENT
# ============================================
$ cat /etc/profile.d/custom.sh
export EDITOR=vim
$ echo $EDITOR
vim
# ============================================
# PART 10: SHELL OPTIONS
# ============================================
$ set -e
$ set -u
$ set -o pipefail
$ set -x
+ ls -l

The ten parts covered shell execution, PATH, variables, export, special variables, exit codes, default values, startup files, system-wide environment, and shell options.


Quick Reference

Command Types

TypeRuns InExample
Built-inThe shellcd, echo, export
ExternalChild processls, grep, find
FunctionThe shellUser-defined
AliasThe shellll='ls -la'

Variable Operations

OperationSyntax
Assignname="value"
Read$name or ${name}
Exportexport name
Unsetunset name
Default${name:-default}
Assign default${name:=default}
Error if unset${name:?error}

Special Variables

VariableValue
$?Exit code of last command
$$PID of the shell
$!PID of last background process
$0Script name
$1โ€“$9Positional parameters
$#Number of positional parameters
$@All positional parameters
$HOMEHome directory
$PATHCommand search path
$USERCurrent user

Bash Startup Files

Shell TypeFiles
Login/etc/profile, ~/.bash_profile
Interactive non-login/etc/bash.bashrc, ~/.bashrc
Non-interactive$BASH_ENV

Shell Options

OptionEffect
set -eExit on error
set -uError on unset variable
set -xPrint commands
set -o pipefailFail on pipeline error

Best Practices

โœ… Do This:

# Use type to find what a command is
type ls                                                       # โœ…

# Export variables that programs need
export EDITOR=vim                                             # โœ…

# Use ${var:-default} for safe expansion
echo "${name:-Bob}"                                           # โœ…

# Check exit codes in scripts
if ! command; then echo "failed"; fi                          # โœ…

# Use set -euo pipefail in scripts
#!/bin/bash
set -euo pipefail                                             # โœ…

# Put environment variables in ~/.bashrc
echo 'export EDITOR=vim' >> ~/.bashrc                         # โœ…

# Put system-wide variables in /etc/profile.d/
echo 'export EDITOR=vim' > /etc/profile.d/custom.sh           # โœ…

โŒ Don’t Do This:

# Don't forget to export variables for child processes
name="Alice"  # child does not see it                          # โŒ

# Don't use $name without quotes
echo $name  # word splitting, globbing                         # โš ๏ธ

# Don't assume the shell reads ~/.bash_profile
# Interactive non-login shells read ~/.bashrc                  # โš ๏ธ

# Don't edit PATH without preserving it
PATH="/new/path"  # loses the old PATH                         # โŒ

# Don't use set -e without understanding it
set -e  # can exit unexpectedly on non-zero returns            # โš ๏ธ

# Don't put aliases in scripts
alias ll='ls -la'  # aliases are not expanded in scripts       # โš ๏ธ

# Don't forget that cd is a built-in
# An external program cannot change the shell's directory       # โœ…

Common Pitfalls

PitfallWhy It HappensFix
Variable empty in childNot exportedexport name
Command not foundNot in PATHAdd to PATH or use full path
~/.bashrc not readLogin shell reads profileSource it or edit the profile
Environment not persistentSet in the current shell onlyAdd to ~/.bashrc
cd in script has no effectRuns in a subshellSource the script or use builtin cd
Exit code ignoredNot checking $?Check $? or use &&
PATH overwrittenAssigned without $PATHPATH="$HOME/bin:$PATH"

Real-World Examples

1. Find a Command

type -a python3
which python3

2. Export a Variable

export EDITOR=vim
echo $EDITOR

3. Persist a Variable

echo 'export EDITOR=vim' >> ~/.bashrc
source ~/.bashrc

4. System-Wide Variable

sudo tee /etc/profile.d/custom.sh << 'EOF'
export EDITOR=vim
EOF

5. Check Exit Code

command
if [ $? -eq 0 ]; then echo "success"; fi

6. Default Value

echo "${EDITOR:-nano}"

7. Add to PATH

export PATH="$HOME/bin:$PATH"

8. Alias

alias ll='ls -la'
ll

9. Debug a Script

bash -x script.sh

10. Robust Script Preamble

#!/bin/bash
set -euo pipefail

Visual

Shell Execution Loop

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  USER TYPES: ls -l /etc/hosts                               โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  1. READ the line from the terminal                         โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  2. TOKENIZE into words: ls, -l, /etc/hosts                 โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  3. EXPAND variables, globs, command substitution           โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  4. RESOLVE the command: built-in? alias? PATH?             โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  5. FORK a child process                                    โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  6. EXEC the command in the child                           โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  7. WAIT for the child to exit                              โ”‚
โ”‚    โ”‚                                                        โ”‚
โ”‚    โ–ผ                                                        โ”‚
โ”‚  8. PRINT the prompt                                        โ”‚
โ”‚                                                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Shell vs Environment Variable

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SHELL VARIABLE                                             โ”‚
โ”‚                                                             โ”‚
โ”‚  name="Alice"                                               โ”‚
โ”‚  Visible only to the current shell                          โ”‚
โ”‚  Not passed to child processes                              โ”‚
โ”‚                                                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                             โ”‚
โ”‚  ENVIRONMENT VARIABLE                                       โ”‚
โ”‚                                                             โ”‚
โ”‚  export name="Alice"                                        โ”‚
โ”‚  Visible to the current shell and all child processes       โ”‚
โ”‚  Passed through fork and exec                               โ”‚
โ”‚                                                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                             โ”‚
โ”‚  PARENT SHELL                                               โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚  name="Alice"  (shell variable)                     โ”‚    โ”‚
โ”‚  โ”‚  export PATH   (environment variable)               โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                        โ”‚ fork + exec                        โ”‚
โ”‚                        โ–ผ                                    โ”‚
โ”‚  CHILD PROCESS                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚  $name  โ†’ empty (not exported)                      โ”‚    โ”‚
โ”‚  โ”‚  $PATH  โ†’ inherited                                 โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                                                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Bash Startup Files

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  LOGIN SHELL (ssh, console, bash --login)                   โ”‚
โ”‚                                                             โ”‚
โ”‚  /etc/profile                                               โ”‚
โ”‚    โ””โ”€โ”€ /etc/profile.d/*.sh                                  โ”‚
โ”‚  ~/.bash_profile                                            โ”‚
โ”‚    โ””โ”€โ”€ sources ~/.bashrc (common pattern)                   โ”‚
โ”‚  ~/.bash_login (if no .bash_profile)                        โ”‚
โ”‚  ~/.profile (if no .bash_profile or .bash_login)            โ”‚
โ”‚                                                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                             โ”‚
โ”‚  INTERACTIVE NON-LOGIN SHELL (terminal in GUI)              โ”‚
โ”‚                                                             โ”‚
โ”‚  /etc/bash.bashrc                                           โ”‚
โ”‚  ~/.bashrc                                                  โ”‚
โ”‚                                                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                             โ”‚
โ”‚  NON-INTERACTIVE SHELL (script)                             โ”‚
โ”‚                                                             โ”‚
โ”‚  $BASH_ENV (if set)                                         โ”‚
โ”‚                                                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Exit Codes

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  EXIT CODE CONVENTION                                       โ”‚
โ”‚                                                             โ”‚
โ”‚  0    โ†’ Success                                             โ”‚
โ”‚  1    โ†’ General error                                       โ”‚
โ”‚  2    โ†’ Misuse of shell built-in                            โ”‚
โ”‚  126  โ†’ Command cannot execute                              โ”‚
โ”‚  127  โ†’ Command not found                                   โ”‚
โ”‚  128+ โ†’ Fatal signal (128 + signal number)                  โ”‚
โ”‚                                                             โ”‚
โ”‚  Check with: echo $?                                        โ”‚
โ”‚  Chain with: cmd1 && cmd2 (cmd2 runs if cmd1 succeeds)      โ”‚
โ”‚  Chain with: cmd1 || cmd2 (cmd2 runs if cmd1 fails)         โ”‚
โ”‚                                                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
ShellProgram that reads and executes commands
Built-inRuns in the shell (cd, echo)
ExternalRuns in a child process (ls, grep)
PATHColon-separated command search path
typeShow how a command resolves
whichShow the PATH location
Shell variableLocal to the shell
Environment variableExported, passed to children
exportPromote to environment
$?Exit code of last command
Login shell files/etc/profile, ~/.bash_profile
Interactive files~/.bashrc
System-wide/etc/profile.d/*.sh

Key takeaways:

  • The shell is a program, not part of the kernel. It reads a line, parses it, expands it, resolves the command, forks a child, executes the command, waits, and prints the prompt. The loop is the interactive session.
  • Built-ins run in the shell; external commands run in a child process. cd must be a built-in because it changes the shell’s state. ls is external because it does not. Use type to find out which a command is.
  • The PATH variable determines where external commands are found. The shell searches the directories in PATH in order. The first match runs. Adding a directory to PATH makes its commands available.
  • Shell variables are local; environment variables are inherited. The export command promotes a shell variable to the environment. Child processes see exported variables, not shell-local ones.
  • The startup files depend on the shell type. A login shell reads /etc/profile and ~/.bash_profile. An interactive non-login shell reads ~/.bashrc. A script reads neither, unless BASH_ENV is set.
  • Exit codes indicate success or failure. 0 means success. Non-zero means failure. The $? variable holds the exit code of the last command. Scripts use exit codes for conditionals.
  • set -euo pipefail is the robust script preamble. It exits on error, treats unset variables as errors, and fails pipelines when any command fails.

Remember: The shell is the interface to the system, and the LFCS is taken entirely in the shell. Understanding what the shell does with a commandโ€”how it parses, expands, resolves, forks, and executesโ€”is understanding where things go wrong when they do. The PATH determines what runs. The environment determines what programs see. The startup files determine what is configured. The exit codes determine what happens next. These are the fundamentals, and every task on the exam is built on them.



Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!