Terminal and Shell
If you have never used a terminal before, this page will get you oriented. If you have, use it as a quick reference. This is not a comprehensive guide; it covers enough to be productive in this course.
Unless noted otherwise, path and log file examples below assume a Linux server rather than macOS.
Terminal vs. Shell
Section titled “Terminal vs. Shell”A terminal (or terminal emulator) is the window you type commands into. A shell is the program running inside that window that interprets your commands and executes them.
Common shells:
- bash (Bourne Again Shell): the default on most Linux servers and older macOS versions.
- zsh (Z Shell): the default on modern macOS. Nearly identical to bash for basic usage.
When you open Terminal on macOS or a WSL window on Windows, you are running a shell inside a terminal. The prompt (something like ubuntu@ip-172-31-0-5:~$ or ulbrical %) tells you who you are, where you are, and that the shell is ready for input. The final prompt character is a useful clue: $ usually means a regular user, # usually means the root user, and % is common in zsh’s default prompt for a regular user. Prompts are customizable, so you may see other formats.
Navigating the Filesystem
Section titled “Navigating the Filesystem”In Unix-like systems, most things you interact with are represented as files or directories. The filesystem also includes other file types, such as symbolic links, devices, and sockets. Paths use forward slashes (/). The root of the filesystem is /.
| Command | What it does | Example |
|---|---|---|
pwd | Print the current directory | pwd |
ls | List files in the current directory | ls -la (all files, detailed) |
cd | Change directory | cd /var/log |
cd .. | Go up one directory | cd .. |
cd ~ | Go to your home directory | cd ~ |
cd - | Go to the previous directory | cd - |
Absolute paths start with / (e.g., /etc/apache2/apache2.conf). Relative paths start from your current directory (e.g., ./config.txt or ../other-dir/).
Working with Files
Section titled “Working with Files”| Command | What it does | Example |
|---|---|---|
cat | Print a file’s contents | cat /etc/hostname |
less | View a file with scrolling (press q to quit) | less /var/log/syslog |
head / tail | Show the first/last lines | tail -20 /var/log/syslog |
cp | Copy a file or directory | cp file.txt backup.txt |
mv | Move or rename a file | mv old.txt new.txt |
rm | Remove a file (no undo) | rm temp.txt |
rm -r | Remove a directory and its contents | rm -r old-dir/ |
mkdir | Create a directory | mkdir -p logs/2026 |
touch | Create an empty file or update a timestamp | touch notes.txt |
Searching
Section titled “Searching”grep searches files or command output for lines matching a pattern. It is one of the most-used commands in system administration.
| Flag | What it does | Example |
|---|---|---|
| (none) | Search for a literal string | grep "error" /var/log/syslog |
-r | Search recursively through a directory | grep -r "DB_HOST" /var/www/ |
-i | Case-insensitive match | grep -i "warning" log.txt |
-v | Invert: show lines that do NOT match | grep -v "^#" config.txt |
-n | Show line numbers | grep -n "failed" auth.log |
-c | Count matching lines instead of printing them | grep -c "error" syslog |
-E | Extended regular expressions (enables +, ?, alternation, {n}) | grep -E "errors?" syslog |
-rn | Recursive with line numbers (common combination) | grep -rn "TODO" /var/www/ |
For alternation with extended regular expressions, use |:
grep -E "error|warn" syslogfind locates files by name, type, or other attributes:
find /etc -name "*.conf" # all .conf files under /etcfind /var/log -name "*.log" -mtime -1 # log files modified in the last dayfind /tmp -type f -size +10M # files larger than 10 MB in /tmpwhich tells you where the shell would find a command:
which python3 # /usr/bin/python3Pipes, Redirection, and Streams
Section titled “Pipes, Redirection, and Streams”Every Unix program connects to three standard streams by default:
- stdin (standard input, file descriptor 0): where the program reads input. By default, the keyboard.
- stdout (standard output, file descriptor 1): where the program sends its normal output. By default, the terminal.
- stderr (standard error, file descriptor 2): where the program sends error messages. Also the terminal by default, but kept separate from stdout so that errors do not corrupt piped output.
The distinction between stdout and stderr matters when you redirect output to a file or pipe it to another program. Only stdout flows through a pipe by default. Error messages still appear on the terminal even when normal output is redirected elsewhere, which is usually what you want.
The pipe operator | connects one command’s stdout directly to the next command’s stdin. Each program does one thing; the shell arranges the plumbing:
grep "error" /var/log/syslog | wc -l # count lines containing "error"du -ah /var | sort -rh | head -10 # 10 largest items in /varps aux | grep nginx | grep -v grep # find nginx processesRedirection
Section titled “Redirection”Redirection sends a stream to a file instead of the terminal, or takes file content as input instead of the keyboard:
echo "hello" > file.txt # write stdout to file (overwrites)echo "world" >> file.txt # append stdout to filecommand 2> errors.log # redirect stderr only to a filecommand > out.log 2>&1 # redirect both stdout and stderr to the same filecommand >> out.log 2>&1 # append both (the standard pattern for cron job logs)2>&1 means “send file descriptor 2 (stderr) to wherever file descriptor 1 (stdout) is currently going.” Order matters: write > file 2>&1, not 2>&1 > file. The second form redirects stderr to the terminal first and then moves stdout to the file, which is almost certainly not what you intend.
Producing Output
Section titled “Producing Output”echo prints a string followed by a newline. It is sufficient for simple messages:
echo "Backup complete"echo "Error: file not found" >&2 # send to stderr instead of stdoutprintf gives precise control over formatting. It does not append a newline automatically, so you add \n explicitly:
printf "%-20s %s\n" "Directory" "Status"printf "%-20s %s\n" "/var/www/html" "OK"printf "%d files processed\n" 42Reading Input
Section titled “Reading Input”The read builtin captures a line from stdin and stores it in a variable. Use -r to disable backslash interpretation (almost always what you want). Prompt flags differ between shells, so the most portable pattern is to print the prompt separately:
printf "Enter the destination path: "read -r DESTecho "You entered: $DEST"In bash, read -rp "Enter the destination path: " DEST combines those two steps.
Inside a script, read is commonly used in a while loop to process a file or command output line by line.
Process Substitution
Section titled “Process Substitution”Process substitution (<(command)) makes the output of a command appear as a file path. It is useful when a command expects file arguments rather than piped input:
diff <(ls /etc/nginx/conf.d) <(ls /etc/nginx/sites-enabled)Both ls commands run concurrently and diff compares their outputs as if they were two files. Process substitution is supported by shells such as bash, zsh, and ksh, but it is not available in plain POSIX sh scripts.
File Permissions
Section titled “File Permissions”Every file has an owner, a group, and permissions for read (r), write (w), and execute (x). In ls -l output, the first character shows the file type.
ls -l script.sh# -rwxr-xr-- 1 ubuntu www-data 512 Mar 15 script.sh# ^ file type (- = regular file, d = directory, l = symbolic link)# ^^^ owner permissions (rwx)# ^^^ group permissions (r-x)# ^^^ others permissions (r--)| Command | What it does | Example |
|---|---|---|
chmod | Change file permissions | chmod +x script.sh |
chmod 755 | Set specific permissions (owner rwx, group r-x, others r-x) | chmod 755 script.sh |
chown | Change file owner | sudo chown www-data:www-data index.html |
The numeric form (like 755) encodes permissions as three digits: owner, group, others. Each digit is the sum of read (4), write (2), and execute (1). So 755 means rwxr-xr-x.
sudo and su
Section titled “sudo and su”sudo runs a single command as the superuser (root). Most system administration tasks require it.
sudo apt update # Update package listssudo systemctl restart nginx # Restart a servicesudo vim /etc/hosts # Edit a system fileUse sudo only when necessary. Running everything as root is a security risk because any mistake, or any compromised command, has unrestricted access to the system.
su (substitute user) switches your entire session to another user rather than running a single command. su - (with a hyphen) switches to root and loads a full login environment, including root’s PATH and profile:
su - # become root (requires root's password)su - deploy # become the "deploy" userexit # return to your original userOn Ubuntu and some other distributions, the root account is locked by default, so su - to root may fail unless a root password has been set.
On most modern Linux servers, sudo is preferred over su - because it leaves an audit trail of who ran what and does not require sharing the root password. su is more common in environments where sudo is not configured.
Package Managers
Section titled “Package Managers”Package managers install, update, and remove software. The package manager depends on your distribution.
| Distribution | Manager | Install example |
|---|---|---|
| Ubuntu/Debian | apt | sudo apt install nginx |
| Amazon Linux/RHEL | dnf / yum | sudo dnf install nginx |
| macOS | brew | brew install wget |
On Debian and Ubuntu, run sudo apt update before installing packages to refresh the package list. Other package managers handle repository metadata differently.
Environment Variables
Section titled “Environment Variables”Environment variables store configuration that programs and scripts can read. They are written in ALL_CAPS by convention. Every process has its own set of environment variables, inherited from the process that started it. When you open a terminal, your shell inherits variables set by the system and by your shell configuration files. When you run a command, that command inherits your shell’s environment.
echo $HOME # your home directoryecho $USER # your usernameecho $SHELL # your current shellprintenv # print all environment variablesShell Variables vs. Environment Variables
Section titled “Shell Variables vs. Environment Variables”A plain assignment creates a shell variable, local to the current shell session:
MY_VAR="hello"echo $MY_VAR # hellobash -c 'echo $MY_VAR' # (empty — child process does not see it)Adding export promotes it to an environment variable, which child processes inherit:
export MY_VAR="hello"bash -c 'echo $MY_VAR' # helloScripts you run in the terminal, CLI tools, and programs launched from the shell all run as child processes. They see exported variables but not plain shell variables.
Persistence
Section titled “Persistence”Variables set in a terminal session disappear when you close the terminal. To make them permanent, add the export line to your shell configuration file:
- bash:
~/.bashrc(interactive non-login shells, the common case on Linux servers) or~/.bash_profile(login shells). - zsh:
~/.zshrc.
After editing the file, reload it in your current session:
source ~/.bashrc # bashsource ~/.zshrc # zshPATH is a colon-separated list of directories the shell searches when you type a command. The shell tries each directory in order and runs the first match:
echo $PATHwhich python3 # shows which python3 the shell would runTo add a directory to PATH for the current session:
export PATH="$HOME/.local/bin:$PATH"Place the new directory before $PATH (at the start) to make it take priority over system-installed versions. Add the same line to ~/.bashrc or ~/.zshrc to make it permanent.
SSH (Secure Shell) connects you to a remote machine over an encrypted channel. You will use it constantly in this course.
# Connect to a remote serverssh -i ~/Downloads/cs312-key.pem ubuntu@54.123.45.67
# Copy a file to a remote serverscp file.txt ubuntu@54.123.45.67:/home/ubuntu/
# Copy a file from a remote serverscp ubuntu@54.123.45.67:/var/log/syslog ./syslog-copy.txtIf SSH says your private key permissions are too open and refuses to use it, fix the permissions:
chmod 400 ~/Downloads/cs312-key.pemGetting Help
Section titled “Getting Help”When you encounter an unfamiliar command, these are the fastest ways to learn what it does:
man ls # Open the manual page for "ls" (press q to quit)type cd # Ask the shell what "cd" is (builtin, alias, function, or executable)tldr tar # Community-maintained cheat sheetsReading manual pages (man) is a core skill. The format is dense at first but becomes natural with practice. Many commands also support -h or --help, but those flags are not standardized and can differ between Linux and macOS. If you want TLDR pages, install a client for your platform first. For example, Homebrew currently packages tlrc on macOS, while Linux distributions may package tldr, tealdeer, or another client.