My Notes

Linux Notes

Linux 4 September 2026

Keyboard Shortcuts

Cursor & Line Editing

Key What it does
Ctrl+A Move cursor to beginning of line
Ctrl+E Move cursor to end of line
Ctrl+B / Move cursor one character left
Ctrl+F / Move cursor one character right
Alt+B Move cursor one word left
Alt+F Move cursor one word right
Ctrl+W Delete word to the left of cursor
Ctrl+K Cut from cursor to end of line
Ctrl+U Cut from cursor to beginning of line
Ctrl+Y Paste (yank) the last cut text
Ctrl+T Swap the two characters before cursor

History Navigation

Key What it does
Ctrl+P / Previous command in history
Ctrl+N / Next command in history
Ctrl+R Reverse search through history (type to filter)
Ctrl+G Cancel history search, return to prompt
!! Repeat last command
!$ Last argument of previous command
!abc Run most recent command starting with "abc"
history Show numbered command history list
!123 Run command number 123 from history

Process & Job Control

Key What it does
Ctrl+C Send SIGINT — interrupt (kill) current process
Ctrl+Z Suspend current process, send to background
Ctrl+D Send EOF — closes current terminal/session
Ctrl+\\ Send SIGQUIT — force quit with core dump
fg Bring suspended job to foreground
bg Resume suspended job in background
jobs List all background/suspended jobs
command & Run command in background immediately

Tab Completion & Other Tricks

Key What it does
Tab Auto-complete command, filename, or path
Tab Tab Show all possible completions when ambiguous
Ctrl+L Clear the screen (same as clear)
Ctrl+S Pause terminal output (scroll lock)
Ctrl+Q Resume terminal output (unlock scroll)
Alt+. Insert last argument of previous command
Ctrl+X Ctrl+E Open current command in $EDITOR for editing

Quick Reference Commands

Navigation
cd -          # go back to previous directory
cd ~          # go to home directory
pwd           # print current directory path
ls -lah       # list with sizes, hidden files, human-readable
Find & Search
grep -r "text" .          # search recursively in current dir
find . -name "*.txt"      # find files by name pattern
find . -mmin -60          # files modified in last 60 minutes
which command             # show full path of a command
File & Disk
du -sh *          # size of each item in current dir
df -h             # disk space on all mounted filesystems
stat file.txt     # detailed file info (size, permissions, times)
wc -l file.txt    # count lines in a file
Process & System
ps aux | grep name    # find a running process by name
kill -9 PID           # force kill a process by PID
top                   # live process viewer (q to quit)
free -h               # RAM usage in human-readable format
uptime                # how long the system has been running

File Permissions & Ownership

Understanding the Permission String

Every file in Linux has a 10-character permission string shown by ls -l. Example: drwxr-xr-x

Position(s)Meaning
d (pos 1)File type: d=directory, -=regular file, l=symlink, b=block device, c=char device, p=pipe, s=socket
rwx (pos 2-4)Owner permissions: read, write, execute
r-x (pos 5-7)Group permissions: read, no write, execute
r-x (pos 8-10)Others permissions: read, no write, execute
rRead (4): view file contents / list directory
wWrite (2): modify file / create or delete files in directory
xExecute (1): run as program / enter directory (cd)

chmod — Numeric Mode

Each permission group is a sum of: read=4, write=2, execute=1. Three digits: owner, group, others.

CommandResult
chmod 644 fileOwner rw-, Group r--, Others r-- (standard file)
chmod 755 fileOwner rwx, Group r-x, Others r-x (standard executable/dir)
chmod 700 fileOwner rwx, Group ---, Others --- (private executable)
chmod 600 fileOwner rw-, Group ---, Others --- (private file, e.g. SSH keys)
chmod 777 fileEveryone rwx (avoid in production)
chmod 400 fileOwner r--, nobody else (read-only, e.g. PEM key files)
chmod 664 fileOwner rw-, Group rw-, Others r-- (shared group write)
chmod -R 755 dir/Apply recursively to directory and all contents

chmod — Symbolic Mode

Symbolic mode uses u (user/owner), g (group), o (others), a (all). Operators: + add, - remove, = set exactly.

CommandWhat it does
chmod u+x fileAdd execute for owner
chmod g-w fileRemove write from group
chmod o=r fileSet others to read-only (removes write/execute)
chmod a+r fileAdd read for everyone
chmod ug+rw fileAdd read+write for owner and group
chmod a-x fileRemove execute from all
chmod u=rwx,go=rx fileOwner full, group+others rx (same as 755)

chown and chgrp

CommandWhat it does
chown alice fileChange owner to alice
chown alice:devs fileChange owner to alice, group to devs
chown :devs fileChange group only (same as chgrp devs file)
chown -R alice:alice dir/Recursively change owner and group
chgrp devs fileChange group to devs
chown --reference=ref.txt fileCopy ownership from ref.txt to file

umask — Default Permission Mask

umask subtracts from the maximum permission. Files start at 666, directories at 777. umask 022 gives files 644 and dirs 755.

Command / ValueWhat it does
umaskShow current umask (e.g. 0022)
umask 022Files: 644, Dirs: 755 (default on most systems)
umask 027Files: 640, Dirs: 750 (group readable, others blocked)
umask 077Files: 600, Dirs: 700 (private: only owner access)
umask -SShow umask in symbolic form (e.g. u=rwx,g=rx,o=rx)
umask calculation
File max:  666 (rw-rw-rw-)
umask:     022 (----w--w-)
Result:    644 (rw-r--r--)

Dir max:   777 (rwxrwxrwx)
umask:     022 (----w--w-)
Result:    755 (rwxr-xr-x)

Special Permission Bits

Bit / CommandWhat it does
SUID (4xxx)Set User ID: executable runs with owner's privileges. Shown as s in owner execute bit. Example: -rwsr-xr-x
chmod u+s fileSet SUID on a file
chmod 4755 fileSet SUID numerically (4 prefix)
SGID (2xxx)Set Group ID: executable runs with group's privileges. On directories: new files inherit the directory's group. Shown as s in group execute bit.
chmod g+s dir/Set SGID on a directory
chmod 2775 dir/Set SGID numerically
Sticky bit (1xxx)On directories: only file owner (or root) can delete their own files. Shown as t in others execute bit. Used on /tmp.
chmod +t dir/Set sticky bit on directory
chmod 1777 /tmpStandard /tmp permissions (sticky+rwx for all)
S vs s / T vs tUppercase means the underlying execute bit is NOT set; lowercase means it IS set

Common Permission Patterns

ModeSymbolicTypical use
600rw-------SSH private keys (~/.ssh/id_ed25519)
644rw-r--r--Web files, config files, regular documents
700rwx------Private scripts, ~/.ssh directory
755rwxr-xr-xExecutables, public web directories
775rwxrwxr-xShared group project directories
777rwxrwxrwxWorld-writable (security risk, avoid)
400r--------Read-only PEM/key files from AWS etc.
440r--r-----/etc/sudoers

Process Management

ps — Process Snapshot

CommandWhat it does
ps auxAll processes: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ps aux --sort=-%cpuSort by CPU descending
ps aux --sort=-%memSort by memory descending
ps -efFull-format listing (UID PID PPID C STIME TTY TIME CMD)
ps -p 1234Info for specific PID
ps --ppid 1234Children of process 1234
ps axjfProcess tree with parent-child indentation

ps aux column guide: VSZ = virtual memory size (KB), RSS = resident set size / actual RAM (KB), STAT: R=running, S=sleeping, D=uninterruptible sleep, Z=zombie, T=stopped, s=session leader, +=foreground, l=multi-threaded.

Kill Signals

SignalMeaning & use
kill -1 / SIGHUPHangup — reload config without restart (daemons). Also sent when terminal closes.
kill -2 / SIGINTInterrupt — same as Ctrl+C. Graceful stop.
kill -3 / SIGQUITQuit — like SIGINT but dumps core. Ctrl+\
kill -9 / SIGKILLKill immediately — cannot be caught or ignored. Use as last resort.
kill -15 / SIGTERMTerminate gracefully — default signal for kill. Process can clean up.
kill -18 / SIGCONTContinue a stopped process.
kill -19 / SIGSTOPStop (pause) process — cannot be caught. Like Ctrl+Z but from another process.
kill -20 / SIGTSTPTerminal stop — Ctrl+Z. Can be caught/ignored unlike SIGSTOP.
kill PIDSend SIGTERM (15) to PID
kill -9 PIDForce-kill PID
kill -lList all signal names and numbers
killall nginxSend SIGTERM to all processes named nginx
killall -9 nginxForce-kill all nginx processes

nice and renice — Process Priority

Niceness ranges from -20 (highest priority) to 19 (lowest priority). Default is 0. Only root can set negative values.

CommandWhat it does
nice -n 10 commandStart command with niceness 10 (lower priority)
nice -n -5 commandStart command with niceness -5 (higher priority, root only)
renice 15 -p 1234Change niceness of running process 1234 to 15
renice -5 -u aliceChange niceness of all alice's processes to -5 (root only)
ps -o pid,ni,commShow PID, niceness, and command name

Background & Foreground Job Control

Command / KeyWhat it does
command &Run command in background from the start
Ctrl+ZSuspend (stop) current foreground process
bgResume suspended job in background
bg %2Resume job number 2 in background
fgBring most recent background job to foreground
fg %2Bring job 2 to foreground
jobsList all background/stopped jobs with job numbers
jobs -lList jobs with PIDs
disown %1Remove job 1 from job table (survives terminal close, but no SIGHUP protection)
disown -h %1Mark job to not receive SIGHUP when terminal closes
nohup command &Run command immune to hangup; output goes to nohup.out
nohup command > out.log 2>&1 &nohup with custom log file

pgrep and pkill

CommandWhat it does
pgrep nginxList PIDs of processes matching "nginx"
pgrep -l nginxList PIDs and names
pgrep -u aliceList PIDs of all alice's processes
pkill nginxSend SIGTERM to all processes named nginx
pkill -9 nginxForce-kill all nginx processes
pkill -u aliceKill all processes owned by alice
pkill -f "python script.py"Kill by full command line match (-f matches entire cmd)

lsof and fuser

CommandWhat it does
lsof -i :80What process is using port 80
lsof -i tcp:443What process is using TCP port 443
lsof -p 1234All files opened by PID 1234
lsof -u aliceAll files opened by user alice
lsof /var/log/syslogWhich process has this file open
fuser 80/tcpPID using port 80/tcp
fuser -k 80/tcpKill process using port 80/tcp
fuser /mnt/usbWhich process is using the mount point (preventing unmount)

/proc Filesystem Quick Reference

PathWhat it contains
/proc/PID/cmdlineFull command line of process (null-separated)
/proc/PID/statusHuman-readable process status (Name, State, Pid, VmRSS etc)
/proc/PID/fd/Directory of file descriptors (symlinks to open files)
/proc/PID/mapsMemory map (shared libraries, stack, heap addresses)
/proc/cpuinfoCPU model, cores, flags
/proc/meminfoRAM stats: MemTotal, MemFree, MemAvailable, Buffers, Cached
/proc/loadavgLoad averages (1m, 5m, 15m), running/total threads, last PID
/proc/uptimeSeconds since boot, seconds idle
/proc/net/tcpTCP connections in hex format

Linux Networking Commands

ip — Modern Network Configuration

CommandWhat it does
ip addr showShow all interfaces with IP addresses
ip addr show eth0Show info for eth0 only
ip addr add 192.168.1.50/24 dev eth0Assign IP to interface (temporary)
ip addr del 192.168.1.50/24 dev eth0Remove IP from interface
ip link showShow link-layer (MAC, state UP/DOWN) for all interfaces
ip link set eth0 upBring interface up
ip link set eth0 downBring interface down
ip route showShow routing table
ip route add default via 192.168.1.1Add default gateway
ip route add 10.0.0.0/8 via 192.168.1.254Add static route
ip route del 10.0.0.0/8Delete route
ip neigh showShow ARP table

ss — Socket Statistics (replaces netstat)

CommandWhat it does
ss -tulpnAll TCP/UDP listening ports with process names and PIDs
ss -tAll established TCP connections
ss -uUDP sockets
ss -lListening sockets only
ss -pShow process using the socket
ss -nNumeric (don't resolve names)
ss -sSummary statistics
ss -4 / ss -6IPv4 only / IPv6 only
ss 'sport = :22'Filter by source port 22

Flag breakdown for ss -tulpn: t=TCP, u=UDP, l=listening, p=process, n=numeric

ping, traceroute, mtr

CommandWhat it does
ping -c 4 8.8.8.8Send 4 ICMP echo requests to 8.8.8.8
ping -i 0.2 hostPing every 0.2 seconds (flood ping: -i 0 needs root)
ping -s 1400 hostSend 1400-byte packets (test MTU)
ping6 hostPing via IPv6
traceroute hostShow each hop to destination (uses UDP by default)
traceroute -T hostUse TCP SYN packets (better through firewalls)
traceroute -I hostUse ICMP echo (like Windows tracert)
mtr hostCombines ping + traceroute in real-time display
mtr --report hostmtr report mode (non-interactive, good for logging)
mtr -n hostmtr without DNS resolution

curl — HTTP Requests

CommandWhat it does
curl https://example.comGET request, print body to stdout
curl -I https://example.comHEAD request — show response headers only
curl -L https://example.comFollow redirects
curl -o file.html https://example.comSave output to file.html
curl -O https://example.com/file.zipSave with remote filename
curl -X POST -d 'key=val' URLPOST with form data
curl -X POST -H 'Content-Type: application/json' -d '{"key":"val"}' URLPOST JSON body
curl -H 'Authorization: Bearer TOKEN' URLSet custom header
curl -u user:pass URLHTTP Basic Authentication
curl -s URLSilent mode (no progress bar)
curl -v URLVerbose: show request and response headers
curl -k URLIgnore SSL certificate errors
curl -x http://proxy:3128 URLUse HTTP proxy
curl --max-time 10 URLTimeout after 10 seconds

dig and nslookup — DNS Lookups

CommandWhat it does
dig example.comA record lookup (default)
dig example.com MXMail exchange records
dig example.com TXTTXT records (SPF, DKIM, etc)
dig example.com NSName server records
dig -x 8.8.8.8Reverse DNS lookup (PTR record)
dig @8.8.8.8 example.comQuery specific DNS server
dig +short example.comShort output — just the answer
dig +trace example.comTrace full DNS resolution from root
nslookup example.comSimple DNS lookup
nslookup example.com 1.1.1.1Query Cloudflare DNS

nc (Netcat) and wget

CommandWhat it does
nc -zv host 80Test if port 80 is open (z=scan, v=verbose)
nc -zv host 20-80Scan port range 20-80
nc -l 4444Listen on port 4444
nc host 4444Connect to host port 4444
nc -l 4444 > received.txtReceive file over netcat
nc host 4444 < file.txtSend file over netcat
wget https://example.com/file.zipDownload file
wget -r -np https://example.com/dir/Recursive download (no parent)
wget -c URLContinue interrupted download
wget -q URLQuiet mode
wget -O outfile URLSave to specific filename

Network Config Files

File / PathPurpose
/etc/hostsStatic hostname-to-IP mappings. Checked before DNS. Format: 192.168.1.10 myserver
/etc/resolv.confDNS resolver config. nameserver 8.8.8.8, search example.com, domain example.com
/etc/hostnameSystem hostname
/etc/nsswitch.confOrder of hostname resolution: hosts: files dns means check /etc/hosts first
/etc/network/interfacesNetwork interface config (Debian/Ubuntu traditional)
/etc/netplan/*.yamlNetplan config (modern Ubuntu)

Text Processing Tools

grep — Search Text

Command / FlagWhat it does
grep "pattern" filePrint lines matching pattern
grep -r "pattern" dir/Recursive search through directory
grep -i "pattern" fileCase-insensitive match
grep -v "pattern" fileInvert: lines NOT matching
grep -n "pattern" fileShow line numbers
grep -c "pattern" fileCount matching lines
grep -l "pattern" *.txtList filenames that contain match (not lines)
grep -A 3 "pattern" fileShow 3 lines After each match
grep -B 3 "pattern" fileShow 3 lines Before each match
grep -C 3 "pattern" fileShow 3 lines Context (before and after)
grep -E "pat1|pat2" fileExtended regex: match either pattern
grep -P "\d{3}-\d{4}" filePerl-compatible regex (PCRE)
grep -w "word" fileMatch whole word only
grep -o "pattern" filePrint only the matching part, not the whole line
grep -F "literal" fileFixed string (no regex, faster)

sed — Stream Editor

CommandWhat it does
sed 's/old/new/' fileReplace first occurrence per line
sed 's/old/new/g' fileReplace all occurrences per line (global)
sed 's/old/new/2' fileReplace 2nd occurrence per line
sed -i 's/old/new/g' fileEdit file in-place (modifies file directly)
sed -i.bak 's/old/new/g' fileEdit in-place, backup original as file.bak
sed '5d' fileDelete line 5
sed '/pattern/d' fileDelete all lines matching pattern
sed -n '5,10p' filePrint only lines 5-10 (-n suppresses default print)
sed -n '/start/,/end/p' filePrint lines from /start/ to /end/ pattern
sed '1i\New first line' fileInsert line before line 1
sed '$a\New last line' fileAppend line after last line
sed 's/\t/ /g' fileReplace tabs with spaces
sed '/^$/d' fileDelete blank lines
sed 's/^/PREFIX: /' filePrepend text to every line

awk — Pattern & Action Processing

CommandWhat it does
awk '{print $1}' filePrint first field (space-separated by default)
awk '{print $NF}' filePrint last field ($NF = number of fields)
awk -F: '{print $1}' /etc/passwdUse : as field delimiter, print first field
awk '{print $1, $3}' filePrint fields 1 and 3 (comma adds OFS separator)
awk 'NR==5' filePrint only line 5 (NR = record/line number)
awk 'NR>=5 && NR<=10' filePrint lines 5 through 10
awk '/pattern/{print}' filePrint lines matching pattern
awk '{sum+=$1} END{print sum}' fileSum first column
awk 'BEGIN{print "start"} {print} END{print "end"}' fileRun code before and after processing
awk '{print NF}' filePrint number of fields per line
awk 'length($0) > 80' filePrint lines longer than 80 chars
awk '!seen[$0]++' fileRemove duplicate lines (preserving order)

cut, sort, uniq

CommandWhat it does
cut -d: -f1 /etc/passwdExtract field 1 with : delimiter
cut -d, -f2,4 file.csvExtract fields 2 and 4 from CSV
cut -c1-10 fileExtract characters 1-10 from each line
sort fileSort lines alphabetically
sort -n fileSort numerically
sort -r fileReverse order
sort -u fileSort and remove duplicates
sort -k2 fileSort by field 2
sort -k2 -n fileSort by field 2 numerically
sort -t: -k3 -n /etc/passwdSort /etc/passwd by UID (field 3)
uniq fileRemove consecutive duplicate lines (sort first)
uniq -c filePrefix each line with count of occurrences
uniq -d filePrint only duplicate lines
uniq -u filePrint only unique lines (no duplicates)

tr, wc, head, tail, xargs

CommandWhat it does
tr 'a-z' 'A-Z' < fileConvert lowercase to uppercase
tr -d '\r' < fileDelete carriage returns (Windows line endings)
tr -s ' ' < fileSqueeze multiple spaces into one
tr '[:space:]' ' ' < fileSplit whitespace into separate lines
wc -l fileCount lines
wc -w fileCount words
wc -c fileCount bytes
wc -m fileCount characters (handles multi-byte)
head -n 20 fileFirst 20 lines
head -n -5 fileAll lines except last 5
tail -n 20 fileLast 20 lines
tail -f /var/log/syslogFollow file as it grows (live log viewing)
tail -n +5 filePrint from line 5 onwards (skip first 4)
xargsBuild and execute commands from stdin
find . -name "*.log" | xargs rmDelete all .log files found
cat list.txt | xargs -I{} cp {} /backup/Copy each filename from list.txt to /backup/
xargs -n1 -P4 commandRun command in parallel with 4 processes, 1 arg each

Practical Pipelines

Common one-liners
# Top 10 most common IPs in access.log
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10

# Count non-empty lines in a file
grep -c . file.txt

# Find lines matching pattern, extract 2nd field
grep "ERROR" app.log | awk '{print $2}' | sort | uniq -c

# Replace all occurrences in multiple files
grep -rl "oldtext" . | xargs sed -i 's/oldtext/newtext/g'

# Show unique HTTP status codes from nginx log
awk '{print $9}' access.log | sort | uniq -c | sort -rn

# Remove blank lines and comment lines (#) from a config file
grep -v '^\s*#' config.conf | grep -v '^\s*$'

# Extract email addresses from a file
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' file.txt

Bash Scripting Reference

Variables and Special Variables

Variable / SyntaxMeaning
VAR=valueAssign variable (no spaces around =)
$VAR or ${VAR}Reference variable value (braces required before text)
readonly VAR=valueMake variable read-only (cannot be changed)
local VAR=valueFunction-scoped variable (only inside function)
export VAR=valueExport to environment (child processes inherit it)
unset VARDelete variable
$0Script name / path
$1 $2 ... $9Positional arguments
$#Number of arguments
$@All arguments as separate words (use in loops)
$*All arguments as single string
$?Exit status of last command (0=success, non-zero=error)
$$Current shell PID
$!PID of last background command
$_Last argument of previous command
$IFSInternal Field Separator (default: space, tab, newline)

String Operations

SyntaxWhat it returns
${#VAR}Length of string in VAR
${VAR:2}Substring starting at position 2
${VAR:2:5}Substring: 5 characters starting at position 2
${VAR/old/new}Replace first occurrence of old with new
${VAR//old/new}Replace all occurrences of old with new
${VAR^^}Convert to UPPERCASE
${VAR,,}Convert to lowercase
${VAR:-default}Use default if VAR is unset or empty
${VAR:=default}Set VAR to default if unset/empty, then use it
${VAR:?error msg}Exit with error message if VAR is unset/empty
${VAR#prefix}Remove shortest prefix match
${VAR##prefix}Remove longest prefix match
${VAR%suffix}Remove shortest suffix match
${VAR%%suffix}Remove longest suffix match

Arrays

SyntaxWhat it does
arr=(a b c d)Declare indexed array
declare -a arrExplicitly declare indexed array
arr[0]="first"Assign element at index 0
${arr[2]}Access element at index 2
${arr[@]}All elements (as separate words)
${#arr[@]}Number of elements
arr+=("new")Append element to array
unset arr[2]Remove element at index 2
declare -A mapDeclare associative array (hash map)
map[key]="value"Set associative array element
${map[key]}Get value for key
${!map[@]}All keys of associative array

Conditionals and Test Operators

OperatorTests for
-f fileFile exists and is a regular file
-d dirDirectory exists
-e pathPath exists (any type)
-r fileFile exists and is readable
-w fileFile exists and is writable
-x fileFile exists and is executable
-z "$str"String is empty (zero length)
-n "$str"String is non-empty
"$a" = "$b"Strings are equal (use = not == inside [ ])
"$a" != "$b"Strings are not equal
$a -eq $bIntegers are equal
$a -ne $bIntegers not equal
$a -lt $bInteger less than
$a -le $bInteger less than or equal
$a -gt $bInteger greater than
$a -ge $bInteger greater than or equal
! conditionNegate condition
-s fileFile exists and has size > 0
file1 -nt file2file1 is newer than file2
file1 -ot file2file1 is older than file2

Loops and Control Flow

if / elif / else
if [ -f "$FILE" ]; then
    echo "File exists"
elif [ -d "$FILE" ]; then
    echo "It is a directory"
else
    echo "Not found"
fi

# Double brackets allow &&, ||, regex
if [[ "$str" =~ ^[0-9]+$ ]]; then
    echo "All digits"
fi
for loops
# for-in list
for fruit in apple banana cherry; do
    echo "$fruit"
done

# for-in array
for item in "${arr[@]}"; do
    echo "$item"
done

# C-style
for (( i=0; i<10; i++ )); do
    echo "$i"
done

# with glob
for f in /etc/*.conf; do
    echo "$f"
done
while / until / functions / trap
# while loop
count=0
while [ $count -lt 5 ]; do
    echo "count: $count"
    (( count++ ))
done

# read lines from file
while IFS= read -r line; do
    echo "Line: $line"
done < file.txt

# until loop (opposite of while)
until ping -c1 server &>/dev/null; do
    echo "Waiting for server..."
    sleep 5
done

# function with local vars and return
greet() {
    local name="$1"
    echo "Hello, $name"
    return 0
}
greet "Alice"
echo "Exit: $?"

# here-doc
cat <
                

Package Management

apt — High-Level Package Manager (Debian/Ubuntu)

CommandWhat it does
apt updateRefresh package lists from repositories
apt upgradeUpgrade all upgradable packages
apt full-upgradeUpgrade + handle changed dependencies (may remove packages)
apt install nginxInstall nginx
apt install nginx=1.24.0*Install specific version
apt remove nginxRemove package, keep config files
apt purge nginxRemove package AND config files
apt autoremoveRemove automatically-installed packages no longer needed
apt search keywordSearch package names and descriptions
apt show nginxShow package details: version, size, description, deps
apt list --installedList all installed packages
apt list --upgradableList packages with available upgrades
apt-get cleanRemove downloaded .deb files from cache
apt-get autocleanRemove only obsolete cached packages

apt-cache — Query the Package Cache

CommandWhat it does
apt-cache search nginxSearch package names and descriptions
apt-cache show nginxShow package metadata
apt-cache depends nginxShow what nginx depends on
apt-cache rdepends nginxShow packages that depend on nginx (reverse deps)
apt-cache policy nginxShow installed version, candidate, and pin priority

dpkg — Low-Level Package Tool

CommandWhat it does
dpkg -i package.debInstall a .deb file
dpkg -r nginxRemove package (keep config)
dpkg -P nginxPurge package (remove config too)
dpkg -lList all installed packages
dpkg -l 'nginx*'List packages matching pattern
dpkg -L nginxList all files installed by nginx
dpkg -S /usr/bin/lsWhich package owns this file
dpkg --get-selectionsExport list of all package selections
dpkg --set-selections < pkglistImport package selections
dpkg-query -W -f='${Status}' nginxCheck installation status of nginx

Held Packages and PPAs

CommandWhat it does
apt-mark hold nginxPin nginx to current version (prevents upgrade)
apt-mark unhold nginxRemove hold on nginx
apt-mark showholdList all held packages
add-apt-repository ppa:user/repoAdd a PPA (Personal Package Archive)
add-apt-repository --remove ppa:user/repoRemove a PPA

snap — Containerized Packages

CommandWhat it does
snap install code --classicInstall VS Code snap (classic=unrestricted)
snap remove codeRemove a snap
snap listList installed snaps with version and tracking channel
snap find keywordSearch Snap Store
snap info codeShow details, versions, channels
snap refreshUpdate all snaps
snap refresh codeUpdate a specific snap
snap revert codeRevert snap to previous version

/etc/apt/sources.list Structure

/etc/apt/sources.list format
# Format: deb [options] uri suite components
deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu noble-security main restricted universe multiverse

# Signed-by with modern key format
deb [signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable

# Additional sources go in /etc/apt/sources.list.d/
# e.g. /etc/apt/sources.list.d/docker.list

Components: main=officially supported FOSS, restricted=non-free drivers, universe=community FOSS, multiverse=non-free software

SSH & Remote Access

Basic SSH Usage

CommandWhat it does
ssh user@hostConnect to host as user
ssh -p 2222 user@hostConnect on non-standard port 2222
ssh -i ~/.ssh/mykey user@hostUse specific private key file
ssh -v user@hostVerbose: debug connection issues (-vvv for more)
ssh -X user@hostEnable X11 forwarding (run GUI apps)
ssh -A user@hostForward SSH agent (use local keys on remote)
ssh user@host 'command'Run single command on remote, then exit
ssh -t user@host 'sudo bash'Force pseudo-TTY allocation (for interactive remote commands)

scp — Secure Copy

CommandWhat it does
scp file.txt user@host:/remote/path/Copy local file to remote
scp user@host:/remote/file.txt ./Copy remote file to local directory
scp -r dir/ user@host:/remote/Recursively copy directory
scp -P 2222 file user@host:/path/Use non-standard port (uppercase -P)
scp -i ~/.ssh/key file user@host:/path/Use specific identity file
scp user1@host1:/file user2@host2:/dir/Copy between two remote hosts

rsync — Efficient Sync & Transfer

CommandWhat it does
rsync -avz src/ user@host:/dst/Sync dir: archive mode, verbose, gzip compress
rsync -avz --progress src/ dst/Show per-file progress
rsync -avz --delete src/ dst/Delete files at destination not in source
rsync -avz -e "ssh -p 2222" src/ user@host:/dst/Use SSH on custom port
rsync -avz --exclude="*.log" src/ dst/Exclude log files
rsync -avz --exclude-from=exclude.txt src/ dst/Exclude patterns from file
rsync -n -avz src/ dst/Dry run (show what would be done, no changes)
rsync -avz --checksum src/ dst/Compare by checksum not timestamp/size

rsync flag meanings: a=archive (rlptgoD), r=recursive, l=symlinks, p=permissions, t=timestamps, g=group, o=owner, D=device files, v=verbose, z=compress

SSH Key Generation

CommandWhat it does
ssh-keygen -t ed25519 -C "comment"Generate Ed25519 key (recommended, modern)
ssh-keygen -t rsa -b 4096 -C "comment"Generate RSA 4096-bit key (wider compatibility)
ssh-keygen -f ~/.ssh/mykeySpecify key file name/path
ssh-keygen -p -f ~/.ssh/mykeyChange passphrase on existing key
ssh-keygen -y -f ~/.ssh/mykeyShow public key from private key file
ssh-copy-id user@hostCopy default public key to remote authorized_keys
ssh-copy-id -i ~/.ssh/mykey.pub user@hostCopy specific public key
ssh-copy-id -p 2222 user@hostCopy to host on non-standard port
Manual authorized_keys setup
# On the remote server:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
cat >> ~/.ssh/authorized_keys << 'EOF'
ssh-ed25519 AAAA...your-public-key... comment
EOF
chmod 600 ~/.ssh/authorized_keys

~/.ssh/config — Client Config File

~/.ssh/config example
Host myserver
    HostName 192.168.1.100
    User alice
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    ForwardAgent yes

Host prod
    HostName prod.example.com
    User deploy
    IdentityFile ~/.ssh/prod_key
    StrictHostKeyChecking yes

Host bastion
    HostName bastion.example.com
    User ec2-user
    IdentityFile ~/.ssh/aws.pem

# Jump through bastion to reach internal host
Host internal
    HostName 10.0.1.50
    User admin
    ProxyJump bastion

# Wildcard for all hosts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes

SSH Agent

CommandWhat it does
eval $(ssh-agent -s)Start SSH agent and set environment variables
ssh-add ~/.ssh/id_ed25519Add private key to agent
ssh-add -lList keys currently loaded in agent
ssh-add -d ~/.ssh/id_ed25519Remove specific key from agent
ssh-add -DRemove all keys from agent
ssh-add -t 3600 ~/.ssh/keyAdd key with 1-hour expiry

Port Forwarding and sshfs

CommandWhat it does
ssh -L 8080:localhost:80 user@hostLocal forward: access host's port 80 at localhost:8080
ssh -L 5432:db-server:5432 user@jumpLocal forward through jump host to db-server:5432
ssh -R 8080:localhost:3000 user@hostRemote forward: expose local port 3000 as host:8080
ssh -D 1080 user@hostDynamic: SOCKS5 proxy on localhost:1080
ssh -fN -L 8080:localhost:80 user@hostBackground (-f) no-command (-N) tunnel
sshfs user@host:/remote/path ~/mountpointMount remote directory over SSH
fusermount -u ~/mountpointUnmount sshfs mount

Cron Jobs & Scheduling

crontab — Managing Cron Jobs

CommandWhat it does
crontab -eEdit current user's crontab (opens in $EDITOR)
crontab -lList current user's cron jobs
crontab -rRemove all cron jobs for current user (no confirmation!)
crontab -u alice -eEdit alice's crontab (root only)
crontab -u alice -lList alice's crontab

Cron Syntax

Cron field format
# ┌───────── minute        (0 - 59)
# │ ┌─────── hour          (0 - 23)
# │ │ ┌───── day of month  (1 - 31)
# │ │ │ ┌─── month         (1 - 12 or JAN-DEC)
# │ │ │ │ ┌─ day of week   (0 - 7, 0 and 7 = Sunday, or SUN-SAT)
# │ │ │ │ │
# * * * * *  command to execute

# Special values:
# *   = every (any value)
# ,   = list:  1,15,30
# -   = range: 1-5
# /   = step:  */5 (every 5)

Cron Examples

ScheduleWhen it runs
*/5 * * * *Every 5 minutes
0 * * * *Every hour at :00
0 3 * * *Every day at 3:00 AM
30 8 * * 1-5Weekdays (Mon-Fri) at 8:30 AM
0 0 * * 0Every Sunday at midnight
0 2 1 * *First of every month at 2:00 AM
0 0 1 1 *Every January 1st at midnight
*/15 9-17 * * 1-5Every 15 min during business hours Mon-Fri
0 4 * * 1Every Monday at 4:00 AM
5 0 * 8 *5 minutes after midnight in August
0,30 * * * *Every 30 minutes (at :00 and :30)

Special Cron Strings

StringEquivalent to
@rebootRun once at startup
@yearly / @annually0 0 1 1 *
@monthly0 0 1 * *
@weekly0 0 * * 0
@daily / @midnight0 0 * * *
@hourly0 * * * *

Cron Environment and Logging

Crontab with environment and logging SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MAILTO=admin@example.com # Send all cron mail to root (empty string suppresses mail) # MAILTO="" # Run backup and log output 0 2 * * * /home/alice/backup.sh >> /var/log/backup.log 2>&1 # Run with full path (cron has minimal PATH) @reboot /usr/bin/python3 /home/alice/startup.py >> /var/log/startup.log 2>&1

Cron has a minimal PATH. Always use full paths to commands or set PATH at top of crontab. Redirect stderr too (2>&1) to capture errors.

System Cron Directories

PathPurpose
/etc/crontabSystem crontab (has extra username field)
/etc/cron.d/Package-provided crontab files (same format as /etc/crontab)
/etc/cron.daily/Scripts run daily by run-parts
/etc/cron.weekly/Scripts run weekly
/etc/cron.monthly/Scripts run monthly
/etc/cron.hourly/Scripts run hourly
/var/spool/cron/crontabs/Per-user crontab files (managed by crontab command)

at — One-Time Scheduling

CommandWhat it does
at now + 1 hourSchedule job 1 hour from now (type commands, end with Ctrl+D)
at 14:30Schedule for today at 2:30 PM
at 9am tomorrowSchedule for 9 AM tomorrow
at midnight next fridaySchedule for midnight Friday
echo "command" | at now + 5 minPipe command to at
atqList pending at jobs
atrm 3Remove job number 3 from queue

systemd Timers

CommandWhat it does
systemctl list-timersList all active timers with next trigger time
systemctl list-timers --allList all timers including inactive ones
systemctl enable --now mytimer.timerEnable and start a timer
systemd timer example: /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer

[Timer]
OnCalendar=*-*-* 02:00:00   # Daily at 2 AM
# OnBootSec=5min             # 5 minutes after boot (monotonic)
# OnUnitActiveSec=1h         # Every hour after last activation
Persistent=true              # Run missed jobs after downtime
Unit=backup.service

[Install]
WantedBy=timers.target

OnCalendar syntax: daily, weekly, Mon *-*-* 04:00:00, *-*-* 00/6:00:00 (every 6 hours)

Files, Archives & Search

find — Search for Files

CommandWhat it does
find . -name "*.txt"Find files named *.txt in current directory tree
find / -name "file.conf" 2>/dev/nullFind system-wide, suppress permission errors
find . -iname "*.PNG"Case-insensitive name match
find . -type fRegular files only
find . -type dDirectories only
find . -type lSymbolic links only
find . -maxdepth 2Search at most 2 levels deep
find . -mtime -7Modified in last 7 days (use +7 for older than 7)
find . -mmin -60Modified in last 60 minutes
find . -newer ref.txtFiles newer than ref.txt
find . -size +10MFiles larger than 10 MB (k=KB, M=MB, G=GB)
find . -size -100kFiles smaller than 100 KB
find . -perm 644Files with exactly 644 permissions
find . -perm /u+xFiles with owner execute bit set
find . -user aliceFiles owned by alice
find . -emptyEmpty files or directories
find . -name "*.log" -exec rm {} \;Delete each found file (slower, one rm per file)
find . -name "*.log" -exec rm {} +Delete found files (faster, batches args)
find . -name "*.log" -deleteDelete found files (most efficient)
find . -name "*.txt" -print0 | xargs -0 grep "term"Grep through found files (handles spaces in names)

Links — Hard and Soft

CommandWhat it does
ln file hardlinkCreate hard link (points to same inode; both must be on same filesystem)
ln -s /path/to/target symlinkCreate symbolic link (can cross filesystems, can link dirs)
ls -liShow inode numbers (hard links share same inode)
readlink symlinkShow target of symlink
readlink -f symlinkShow fully resolved absolute path
find . -type lFind all symbolic links
find . -xtype lFind broken symbolic links

Hard link: deleting one doesn't remove data (data survives until all links gone). Symlink: deleting target breaks the link. Directories cannot have hard links (with rare exceptions).

tar — Archiving

CommandWhat it does
tar -czf archive.tar.gz dir/Create gzip-compressed archive
tar -cjf archive.tar.bz2 dir/Create bzip2-compressed archive
tar -cJf archive.tar.xz dir/Create xz-compressed archive (best compression)
tar -cf archive.tar dir/Create uncompressed tar archive
tar -xzf archive.tar.gzExtract gzip archive to current directory
tar -xzf archive.tar.gz -C /target/Extract to specific directory
tar -tf archive.tar.gzList contents without extracting
tar -xzf archive.tar.gz file.txtExtract only specific file
tar -czf archive.tar.gz --exclude="*.log" dir/Create archive excluding .log files
tar -czf - dir/ | ssh user@host 'tar -xzf - -C /dst/'Stream archive directly to remote host

Common flags: c=create, x=extract, t=list, f=file, z=gzip, j=bzip2, J=xz, v=verbose, C=change to directory

Compression Tools

CommandWhat it does
gzip file.txtCompress file.txt to file.txt.gz (removes original)
gzip -k file.txtCompress keeping original
gunzip file.txt.gzDecompress (same as gzip -d)
gzip -l file.gzShow compression ratio
bzip2 file.txtCompress with bzip2 (better ratio, slower than gzip)
bunzip2 file.txt.bz2Decompress bzip2
xz -k file.txtCompress with xz (best ratio, slowest)
unxz file.txt.xzDecompress xz
zip archive.zip file1 file2Create zip archive
zip -r archive.zip dir/Zip directory recursively
unzip archive.zipExtract zip archive
unzip -l archive.zipList zip contents without extracting
unzip archive.zip -d /target/Extract to specific directory

File Information and Manipulation

CommandWhat it does
file document.pdfDetect file type by magic bytes (not extension)
file *Detect type of all files in current directory
stat file.txtShow inode info: size, permissions, timestamps, inode number
dd if=/dev/urandom of=test.img bs=1M count=100Create 100 MB file of random data
dd if=/dev/zero of=zero.img bs=4M count=250Create 1 GB file of zeros
dd if=/dev/sda of=backup.img bs=4MDisk image backup (raw copy of sda)
truncate -s 100M file.imgCreate sparse 100 MB file (or resize existing)
fallocate -l 1G bigfilePre-allocate 1 GB file instantly (not sparse)
shred -vzu -n 3 sensitive.txtOverwrite 3 times, then zero, then delete (-v verbose, -z zero pass, -u delete)
locate filenameFast filename search using database (may be stale)
updatedbUpdate locate database (usually run by cron daily)

Pipes, Redirection & Shell Features

Standard Streams and Redirection

Every process has three default streams: stdin (0), stdout (1), stderr (2).

OperatorWhat it does
> fileRedirect stdout to file (overwrite)
>> fileRedirect stdout to file (append)
2> fileRedirect stderr to file (overwrite)
2>> fileRedirect stderr to file (append)
2>&1Redirect stderr to wherever stdout goes
&> fileRedirect both stdout and stderr to file (bash shorthand)
&>> fileAppend both stdout and stderr to file
> /dev/nullDiscard stdout
> /dev/null 2>&1Discard all output (stdout and stderr)
< fileRedirect file as stdin to command
cmd1 | cmd2Pipe stdout of cmd1 to stdin of cmd2
cmd1 |& cmd2Pipe stdout and stderr of cmd1 to cmd2 (bash)
Common redirection patterns # Capture stdout and stderr to file command > output.log 2>&1 # stderr to separate file command > out.log 2> err.log # Order matters: redirect stderr to where stdout goes command 2>&1 | grep "error" # correct # command | grep "error" 2>&1 # WRONG: 2>&1 affects grep, not command # Discard stderr, keep stdout command 2>/dev/null

tee — Pipe and Save

CommandWhat it does
cmd | tee file.txtWrite stdout to file AND print to terminal
cmd | tee -a file.txtAppend to file while also printing
cmd | tee file1 file2Write to multiple files simultaneously
cmd 2>&1 | tee log.txtCapture stdout+stderr to file and terminal

Process Substitution and Command Substitution

SyntaxWhat it does
$(command)Command substitution: replace with output of command
`command`Command substitution (older backtick form, avoid nesting)
<(command)Process substitution: treat command output as a file (for reading)
>(command)Process substitution: treat command as a file (for writing)
diff <(sort a.txt) <(sort b.txt)Diff sorted versions without creating temp files
tee >(gzip > out.gz) | wc -lCompress and count lines simultaneously

Here-doc, Here-string, and xargs

Here-doc and here-string # Here-doc: multi-line string as stdin cat <
CommandWhat it does
cmd | xargs commandPass stdin lines as arguments to command
cmd | xargs -I{} cp {} /backup/Replace {} with each input line
cmd | xargs -n 2Pass 2 arguments per invocation
cmd | xargs -P 4Run 4 processes in parallel
find . -print0 | xargs -0 rmNull-separated (-0) safe for filenames with spaces
xargs -a file.txt commandRead arguments from file instead of stdin

Subshells, Grouping, and Named Pipes

SyntaxWhat it does
( cmd1; cmd2 )Subshell: runs in child process; variable changes don't affect parent
{ cmd1; cmd2; }Command group: runs in current shell; note trailing semicolon and spaces
( cd /tmp; ls )cd only affects the subshell, not your current directory
mkfifo /tmp/mypipeCreate a named pipe (FIFO)
cmd1 > /tmp/mypipe &Write to named pipe in background
cmd2 < /tmp/mypipeRead from named pipe

Brace Expansion

SyntaxExpands to
echo {a,b,c}a b c
echo file{1,2,3}.txtfile1.txt file2.txt file3.txt
echo {1..5}1 2 3 4 5
echo {01..05}01 02 03 04 05 (zero-padded)
echo {a..z}a b c ... z
echo {1..10..2}1 3 5 7 9 (step of 2)
mkdir -p project/{src,tests,docs}Create 3 subdirectories at once
cp file.txt{,.bak}Copy file.txt to file.txt.bak
mv config{.old,}Rename config.old to config

Vim Editor Reference

Vim Modes

ModeHow to enter / what it is
Normal modeDefault mode. Press Esc from any mode. For navigation and operations.
Insert modePress i to insert before cursor. Status shows -- INSERT --.
Visual modePress v (char), V (line), or Ctrl+v (block). For selection.
Command modePress : from Normal. For file operations and settings.
Replace modePress R from Normal. Overwrites existing characters.

Motion Keys

KeyMovement
h j k lLeft, down, up, right
wNext word start
bPrevious word start
eEnd of current/next word
W B ESame as w/b/e but WORD (space-delimited, ignores punctuation)
0Start of line (column 0)
^First non-whitespace character of line
$End of line
ggFirst line of file
GLast line of file
50G or :50Go to line 50
{ }Previous / next empty line (paragraph movement)
%Jump to matching bracket/paren/brace
Ctrl+dScroll down half page
Ctrl+uScroll up half page
Ctrl+fScroll forward (down) full page
Ctrl+bScroll backward (up) full page
zzCenter current line in window
H M LMove to top / middle / bottom of screen

Editing in Normal Mode

KeyAction
iInsert before cursor
IInsert at start of line
aAppend after cursor
AAppend at end of line
oOpen new line below and enter Insert mode
OOpen new line above and enter Insert mode
xDelete character under cursor
XDelete character before cursor (backspace)
ddDelete (cut) current line
3ddDelete 3 lines
dwDelete from cursor to end of word
d$Delete from cursor to end of line
d0Delete from start of line to cursor
DDelete from cursor to end of line (same as d$)
yyYank (copy) current line
ywYank word
y$Yank to end of line
pPaste after cursor / below current line
PPaste before cursor / above current line
uUndo last change
Ctrl+rRedo (undo the undo)
.Repeat last change (very powerful)
~Toggle case of character under cursor
JJoin current line with next
cwChange word (delete then enter Insert mode)
ccChange entire line
CChange to end of line
rReplace single character (stays in Normal mode)

Search and Replace

CommandWhat it does
/patternSearch forward for pattern
?patternSearch backward for pattern
nNext match (same direction)
NPrevious match (reverse direction)
*Search forward for word under cursor
#Search backward for word under cursor
:%s/old/new/gReplace all occurrences in file
:%s/old/new/gcReplace all with confirmation for each
:%s/old/new/giReplace all case-insensitively
:5,10s/old/new/gReplace only in lines 5-10
:s/old/new/Replace first occurrence on current line
:nohClear search highlighting

Command Mode & Windows

CommandWhat it does
:wSave file
:w filenameSave as filename
:qQuit (fails if unsaved changes)
:q!Quit discarding changes
:wq or :xSave and quit
ZZSave and quit (Normal mode shortcut)
:e filenameOpen file in current buffer
:split / :spHorizontal split
:vsplit / :vspVertical split
Ctrl+w wSwitch between split windows
:tabnewOpen new tab
gt / gTNext / previous tab
:set numberShow line numbers
:set pastePaste mode (disables auto-indent when pasting)
:set nopasteDisable paste mode

Marks and Macros

KeyAction
maSet mark 'a' at current position (a-z: file-local, A-Z: global)
'aJump to line of mark 'a'
`aJump to exact position (line and column) of mark 'a'
:marksList all marks
qaStart recording macro into register 'a'
qStop recording macro
@aPlay macro from register 'a'
10@aPlay macro 10 times
@@Repeat last played macro

Common .vimrc Settings

~/.vimrc essentials set number " Show line numbers set relativenumber " Relative line numbers set tabstop=4 " Tab = 4 spaces wide set shiftwidth=4 " Indent by 4 spaces set expandtab " Use spaces instead of tabs set smartindent " Auto-indent new lines set hlsearch " Highlight search results set incsearch " Incremental search as you type set ignorecase " Case-insensitive search... set smartcase " ...unless search has uppercase set wrap " Wrap long lines set linebreak " Wrap at word boundaries set scrolloff=5 " Keep 5 lines above/below cursor set wildmenu " Command completion menu set clipboard=unnamed " Use system clipboard set backspace=indent,eol,start " Sane backspace syntax on " Syntax highlighting colorscheme desert " Color scheme

Environment & Shell Config

Viewing and Setting Environment Variables

CommandWhat it does
printenvPrint all environment variables
printenv HOMEPrint value of HOME variable
envPrint environment or run command with modified environment
env VAR=val commandRun command with VAR set, without modifying current shell
setPrint all shell variables, functions, and env vars (verbose)
VAR=valueSet shell variable (not exported — child processes don't see it)
export VAR=valueSet and export to environment (child processes inherit it)
export VARExport existing shell variable to environment
unset VARDelete variable from shell and environment
declare -x VAR=valDeclare and export (same as export VAR=val)

Common Environment Variables

VariableMeaning
$HOMECurrent user's home directory (/home/alice)
$USERCurrent username
$SHELLPath to current shell (/bin/bash)
$PWDCurrent working directory (same as pwd command)
$OLDPWDPrevious working directory (cd - uses this)
$PATHColon-separated list of directories searched for commands
$EDITORDefault text editor (used by git commit, crontab -e, etc.)
$VISUALVisual editor (preferred over $EDITOR for interactive use)
$PAGERDefault pager for viewing long output (e.g. less)
$TERMTerminal type (e.g. xterm-256color)
$LANGLocale (e.g. en_US.UTF-8)
$PS1Primary prompt string
$PS2Secondary prompt (shown when command continues)
$HISTSIZENumber of commands kept in history in memory
$HISTFILESIZENumber of commands kept in ~/.bash_history file
$TMPDIRTemporary directory (defaults to /tmp if unset)
$UIDCurrent user's UID (0 = root)

PATH — How It Works

Working with PATH # View current PATH echo $PATH # /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Add directory to PATH (prepend = higher priority) export PATH="/opt/myapp/bin:$PATH" # Add to end of PATH (lower priority) export PATH="$PATH:/opt/legacy/bin" # Make permanent: add to ~/.bashrc or ~/.profile echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # Find which binary will be executed which python3 type python3 # shows alias/function/builtin/file command -v git # portable alternative to which

.bashrc vs .bash_profile vs .profile

FileWhen it runs
~/.bashrcInteractive non-login shells (new terminal tab, bash in X). Aliases, functions, PS1, per-session settings.
~/.bash_profileLogin shells (SSH login, console login). Usually sources ~/.bashrc. Good for export statements.
~/.profileLogin shells for any POSIX shell. Used when .bash_profile doesn't exist. sh-compatible only.
~/.bash_logoutRun when a login bash shell exits.
/etc/profileSystem-wide login shell config (runs for all users).
/etc/bash.bashrcSystem-wide .bashrc (Debian/Ubuntu).
/etc/profile.d/*.shModular scripts sourced by /etc/profile.

Best practice: put exports and PATH changes in ~/.bash_profile (or ~/.profile). Put aliases, functions, and PS1 in ~/.bashrc. Have .bash_profile source ~/.bashrc.

Aliases and Functions

CommandWhat it does
alias ll='ls -lah'Create alias (current session only)
aliasList all current aliases
unalias llRemove alias
type llShow what 'll' resolves to (alias, function, etc.)
\llBypass alias and run original command
~/.bashrc: aliases and functions # Aliases alias ll='ls -lah --color=auto' alias la='ls -A' alias grep='grep --color=auto' alias ..='cd ..' alias ...='cd ../..' alias df='df -h' alias du='du -sh' alias ports='ss -tulpn' # Function: make directory and cd into it mkcd() { mkdir -p "$1" && cd "$1" } # Function: extract any archive extract() { case "$1" in *.tar.gz|*.tgz) tar -xzf "$1" ;; *.tar.bz2) tar -xjf "$1" ;; *.tar.xz) tar -xJf "$1" ;; *.zip) unzip "$1" ;; *.gz) gunzip "$1" ;; *) echo "Unknown format: $1" ;; esac }

PS1 Prompt Customization

PS1 escape codes and examples
# Common PS1 escape sequences:
# \u = username    \h = hostname (short)   \H = hostname (full)
# \w = full CWD    \W = basename of CWD    \$ = # if root else $
# \t = time HH:MM:SS   \d = date
# \n = newline

# ANSI color codes: \[\033[COLORm\]  reset: \[\033[0m\]
# Colors: 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white

# Green user@host, blue directory, reset
PS1='\[\033[32m\]\u@\h\[\033[0m\]:\[\033[34m\]\w\[\033[0m\]\$ '

# Show last exit status (red if error)
PS1='$(if [ $? -eq 0 ]; then echo "\[\033[32m\]OK"; else echo "\[\033[31m\]ERR"; fi)\[\033[0m\] \w \$ '

# With git branch (requires __git_ps1 from git-prompt.sh)
PS1='\[\033[32m\]\u@\h\[\033[0m\]:\[\033[34m\]\w\[\033[33m\]$(__git_ps1 " (%s)")\[\033[0m\]\$ '

source, dot, and exec

CommandWhat it does
source ~/.bashrcExecute script in current shell (variable changes take effect)
. ~/.bashrcSame as source (POSIX dot command)
./script.shRun script in a subshell (changes don't affect current shell)
bash script.shRun script in a new bash subshell
exec bashReplace current shell with new bash (use to reload shell)

User & Group Management

useradd and adduser

useradd is the low-level binary (same on all distros). adduser is a higher-level Debian/Ubuntu script that prompts interactively and creates home dir by default.

CommandWhat it does
useradd aliceCreate user alice (no home dir, no password by default)
useradd -m aliceCreate user with home directory (/home/alice)
useradd -m -s /bin/bash aliceWith home dir and bash shell
useradd -m -G sudo,docker aliceAdd to supplementary groups
useradd -u 1500 aliceSpecify UID
useradd -d /custom/home aliceSet custom home directory
adduser aliceInteractive: create user with home dir, set password (Debian/Ubuntu)
adduser alice sudoAdd existing user alice to sudo group

passwd, usermod, userdel

CommandWhat it does
passwd aliceSet or change alice's password (root)
passwdChange your own password
passwd -l aliceLock account (prefix ! to password hash in /etc/shadow)
passwd -u aliceUnlock account
passwd -e aliceExpire password (force change on next login)
usermod -aG docker aliceAdd alice to docker group (-a means append, not replace)
usermod -G sudo,docker aliceSet supplementary groups (replaces existing groups — use -aG to append)
usermod -L aliceLock account (same as passwd -l)
usermod -U aliceUnlock account
usermod -s /bin/zsh aliceChange login shell
usermod -d /new/home -m aliceChange home directory and move files (-m)
usermod -l newname aliceRename user account
userdel aliceDelete user (keep home directory)
userdel -r aliceDelete user and home directory and mail spool

User Info Commands

CommandWhat it does
idShow current user's UID, GID, and all groups
id aliceShow alice's UID, GID, and groups
whoamiPrint current effective username
groupsList groups current user belongs to
groups aliceList alice's groups
whoWho is logged in right now
wWho is logged in with what they're running
lastHistory of logins from /var/log/wtmp
last aliceLogin history for alice
lastlogMost recent login of every user
lastbFailed login attempts from /var/log/btmp

Group Management

CommandWhat it does
groupadd devsCreate new group devs
groupadd -g 1500 devsCreate group with specific GID
groupdel devsDelete group devs
groupmod -n newname devsRename group
newgrp dockerSwitch primary group to docker for current session (reloads shell)
getent group dockerShow docker group entry (members, GID)

/etc/passwd and /etc/shadow

/etc/passwd format (world-readable) # username:password:UID:GID:GECOS:home:shell alice:x:1001:1001:Alice Smith,,,:/home/alice:/bin/bash # x = password is in /etc/shadow # UID 0 = root, 1-999 = system accounts, 1000+ = regular users
/etc/shadow format (root-readable only) # username:hash:lastchange:minage:maxage:warn:inactive:expire:reserved alice:$6$salt$hashhere...:19600:0:99999:7::: # $6$ = SHA-512, $5$ = SHA-256, $1$ = MD5 (legacy) # ! or !! at start = locked account # lastchange = days since epoch (Jan 1 1970)

sudo and su

CommandWhat it does
sudo commandRun command as root
sudo -u alice commandRun command as alice
sudo -iOpen root login shell (full environment, like logging in as root)
sudo -sOpen root shell keeping current environment
sudo -lList what sudo commands current user can run
sudo -l -U aliceList alice's sudo privileges (as root)
visudoEdit /etc/sudoers safely (validates syntax before saving)
su aliceSwitch to alice (keeps current env; requires alice's password)
su - aliceSwitch to alice with full login shell (loads alice's env)
su -Switch to root login shell
/etc/sudoers rule syntax # Format: WHO WHERE=(AS_WHO:AS_GROUP) WHAT alice ALL=(ALL:ALL) ALL # alice can run any command as any user %devs ALL=(ALL) NOPASSWD: /bin/systemctl restart nginx # %devs = group devs, NOPASSWD = no password prompt bob ALL=(ALL) /usr/bin/apt, /usr/bin/apt-get # bob can only run apt/apt-get deploy ALL=(root) NOPASSWD: /opt/deploy/deploy.sh

Systemd & Service Management

systemctl — Service Control

CommandWhat it does
systemctl start nginxStart service now
systemctl stop nginxStop service now
systemctl restart nginxStop and start service (breaks connections)
systemctl reload nginxReload config without stopping (if supported)
systemctl enable nginxEnable service at boot (creates symlink in wants/)
systemctl disable nginxDisable service at boot
systemctl enable --now nginxEnable AND start immediately
systemctl status nginxShow service status, last log lines, and active state
systemctl is-active nginxPrint "active" or "inactive" (good for scripts)
systemctl is-enabled nginxPrint "enabled" or "disabled"
systemctl list-units --type=serviceList all loaded services
systemctl list-unit-files --type=serviceList all installed services with enabled/disabled status
systemctl list-timersList all active timers with next trigger time
systemctl daemon-reloadReload systemd after adding/changing unit files
systemctl mask nginxPrevent service from being started (links to /dev/null)
systemctl unmask nginxRemove mask
systemctl poweroffShut down system
systemctl rebootReboot system

journalctl — Log Viewer

CommandWhat it does
journalctlAll logs from oldest to newest
journalctl -u nginxLogs for nginx unit only
journalctl -fFollow (live tail) journal logs
journalctl -f -u nginxFollow nginx logs
journalctl -n 50Last 50 lines
journalctl -n 50 -u nginxLast 50 lines of nginx
journalctl --since "1 hour ago"Logs from last hour
journalctl --since "2026-09-04 08:00" --until "2026-09-04 09:00"Logs in time range
journalctl -p errOnly error-level and above messages
journalctl -p warning..errWarning through error priority range
journalctl -bLogs from current boot only
journalctl -b -1Logs from previous boot
journalctl --list-bootsList all boots with IDs and timestamps
journalctl --disk-usageShow journal disk usage
journalctl --vacuum-size=500MKeep only most recent 500 MB of logs
journalctl -o json-pretty -n 5 -u nginxOutput as pretty-printed JSON

Unit File Anatomy

Unit file sections and common directives [Unit] Description=My Web Application # Human-readable name Documentation=https://example.com # Link to docs After=network.target postgresql.service # Start after these Wants=postgresql.service # Soft dependency (start if possible) Requires=network.target # Hard dependency (fail if missing) [Service] Type=simple # simple|forking|oneshot|notify|dbus ExecStart=/usr/bin/python3 /opt/myapp/app.py ExecReload=/bin/kill -HUP $MAINPID # Command for reload ExecStop=/bin/kill -TERM $MAINPID # Graceful stop Restart=on-failure # always|on-failure|on-abort|no RestartSec=5 # Wait 5s before restart User=myapp # Run as this user Group=myapp WorkingDirectory=/opt/myapp Environment="NODE_ENV=production" # Set env var EnvironmentFile=/etc/myapp.env # Load env from file StandardOutput=journal # stdout to journal StandardError=journal # stderr to journal [Install] WantedBy=multi-user.target # Target that should want this unit

Service Types

TypeUse case
simpleExecStart is the main process. Service ready immediately after start. Default.
forkingProcess forks and parent exits. Use PIDFile= to track child. Traditional daemons.
oneshotProcess does a task and exits. Use with RemainAfterExit=yes for status.
notifyLike simple, but service sends sd_notify() when ready. Most reliable for ordering.
dbusService is ready when it takes a D-Bus name. Set BusName=.

Targets (Runlevels)

TargetEquivalent to / purpose
poweroff.targetRunlevel 0 — shut down
rescue.targetRunlevel 1 — single-user/rescue mode
multi-user.targetRunlevel 3 — multi-user, no GUI (servers)
graphical.targetRunlevel 5 — multi-user with GUI
reboot.targetRunlevel 6 — reboot
systemctl get-defaultShow current default target
systemctl set-default multi-user.targetSet server to boot without GUI
systemctl isolate rescue.targetSwitch to rescue mode now

systemd-analyze — Boot Performance

CommandWhat it does
systemd-analyzeTotal boot time: firmware + loader + kernel + userspace
systemd-analyze blameList units sorted by initialization time
systemd-analyze critical-chainShow critical path of boot (slowest chain of dependencies)
systemd-analyze critical-chain nginx.serviceCritical chain to a specific service
systemd-analyze plot > boot.svgGenerate SVG boot timeline (open in browser)
systemd-analyze verify nginx.serviceCheck unit file for errors

Creating a Custom Service

/etc/systemd/system/myapp.service [Unit] Description=My Python App After=network.target Wants=network.target [Service] Type=simple User=myapp Group=myapp WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/venv/bin/python app.py Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal SyslogIdentifier=myapp Environment="PORT=8080" Environment="LOG_LEVEL=info" [Install] WantedBy=multi-user.target
Deploy and start the service # After creating the unit file: systemctl daemon-reload # Reload systemd config systemctl enable --now myapp # Enable + start systemctl status myapp # Verify it's running journalctl -u myapp -f # Follow logs

Drop-in Overrides

CommandWhat it does
systemctl edit nginxOpen override editor; creates /etc/systemd/system/nginx.service.d/override.conf
systemctl edit --full nginxEdit a full copy of the unit file
systemctl revert nginxRemove all overrides and restore package defaults
Override example: add memory limit to nginx # Created by: systemctl edit nginx # Saved to: /etc/systemd/system/nginx.service.d/override.conf [Service] MemoryMax=512M CPUQuota=50%