DEV Community

methew smith
methew smith

Posted on

basic OS commands

Focus: Terminal-first, step-by-step command explanations for practical exam prep


Table of Contents

  1. Linux Basics & File System
  2. Linux Commands & Navigation
  3. File Permissions & Ownership
  4. Users & Groups Management
  5. SSH (Secure Shell)
  6. Apache Web Server
  7. Nginx Web Server
  8. Port Debugging & Troubleshooting
  9. Bash Scripting
  10. Docker Containers
  11. Lab Exercises Summary
  12. Quick Reference Cheat Sheet

1. Linux Basics & File System

What is Linux?

Linux is an open-source operating system kernel. A Linux Distribution (distro) is a collection of software built around the Linux kernel, all licensed under open-source or GPL. 90% of all cloud infrastructure is powered by Linux, making it the foundation of DevOps.

Linux Distributions

  • Debian-based: Ubuntu, Debian — use .deb packages and apt package manager
  • Red Hat-based: CentOS, Fedora, RHEL — use .rpm packages and yum/dnf package manager
  • Technical differences are mainly about package management, software versions, and file locations
  • Once you grasp those differences, switching between distros becomes painless

Choosing a Distribution — Key Questions

  • What is the main function? (Server or Desktop?)
  • What packages are important? (web server, database, etc.)
  • How much disk space is available?
  • How often are packages updated?
  • How long is the support cycle? (LTS = Long Term Support)
  • Do you need long-term stability or cutting-edge software?

Package Management (apt — Debian/Ubuntu)

apt update                    # Update the package index (local DB of available repos)
apt upgrade                   # Upgrade installed packages to latest versions
apt install <pkg_name>        # Install a package
apt remove <pkg_name>         # Remove a package
apt search <pkg_name>         # Search for a package
apt show <pkg_name>           # Show package details
apt list --installed          # List all installed packages
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: Always run apt update BEFORE apt install. Update refreshes the package list, upgrade actually updates the software.

Linux File System Hierarchy

Linux organizes everything in a tree structure starting from / (root):

Directory Purpose
/ Root — top of the entire filesystem tree
/home User home directories (e.g., /home/daniyal)
/etc System configuration files (ssh config, apache config, etc.)
/var Variable data — logs (/var/log), web files (/var/www)
/usr User programs and utilities (/usr/bin, /usr/lib)
/bin Essential command binaries (ls, cp, mv, cat)
/sbin System binaries (systemctl, fdisk) — need root
/tmp Temporary files — cleared on reboot
/opt Optional/third-party software
/root Home directory of the root user
/dev Device files (hardware represented as files)
/proc Virtual filesystem — running process info

🔥 EXAM TIP: Know these paths by heart: /etc/ssh/sshd_config, /var/www/html, /var/log/apache2/, /etc/apache2/sites-available/

OS and Kernel Information

uname -a              # Full system info (kernel name, version, architecture)
lsb_release -a        # Distribution-specific info
cat /etc/os-release   # OS release details
Enter fullscreen mode Exit fullscreen mode

2. Linux Commands & Navigation

Command Structure

A Linux command has three parts: command [options] [arguments]

wc -l devops_course_outline.txt
#  ^    ^    ^
#  |    |    +-- argument (what to operate on)
#  |    +------- option (modifies behavior, starts with - or --)
#  +------------ command (program to execute)
Enter fullscreen mode Exit fullscreen mode

The sudo Command

sudo (superuser do) lets you run commands with root (administrator) privileges:

sudo ls -la /root      # List root's home directory with elevated privileges
sudo apt install nginx  # Install software (needs root)
Enter fullscreen mode Exit fullscreen mode

Directory Navigation

Command What It Does Example
pwd Print current working directory pwd/home/daniyal
cd Change directory cd /var/www/html
cd ~ or cd Go to home directory cd ~
cd .. Go up one level (parent dir) cd ..
cd - Go to previous directory cd -
ls List directory contents ls /etc
ls -la List ALL files (hidden + details) ls -la
tree Show directory tree structure tree /var/www
mkdir Create a directory mkdir myproject
mkdir -p Create nested directories mkdir -p a/b/c
rmdir Remove empty directory rmdir myproject
rm -r Remove directory and contents rm -r myproject

Absolute vs Relative Paths

  • Absolute path: Starts from root /. Example: /usr/bin/python3
  • Relative path: Starts from current directory. Example: ../usr/bin
cd /usr/bin     # Absolute path
cd ../usr/bin   # Relative path
Enter fullscreen mode Exit fullscreen mode

Viewing Files

Command Purpose
cat file.txt Display entire file at once (not ideal for large files)
cat -n file.txt Display with line numbers
tac file.txt Display file in reverse (last line first)
less file.txt Page through large files (scroll up/down, search with /)
head file.txt Show first 10 lines (use -n 20 for first 20)
tail file.txt Show last 10 lines (use -n 20 for last 20)
tail -f file.txt Follow file in real-time (great for logs!)
wc file.txt Count lines, words, characters
wc -l file.txt Count only lines

Creating & Manipulating Files

touch newfile.txt                    # Create empty file (or update timestamp)
touch -t 12091600 file.txt           # Set specific timestamp (Dec 9, 4PM)
echo "hello" > file.txt              # Write to file (OVERWRITES!)
echo "world" >> file.txt             # Append to file
cp source.txt dest.txt               # Copy file
mv old.txt new.txt                   # Rename/move file
rm file.txt                          # Delete file
rm -rf directory/                    # Force delete directory and contents
Enter fullscreen mode Exit fullscreen mode

Searching for Files

The find Command

The find command searches the filesystem in real-time. Extremely useful in DevOps for automation, cleanup, backups, and CI/CD scripts.

find /var/log -name "*.log"           # Find all .log files in /var/log
find /usr -name gcc                   # Find files/dirs named gcc
find /usr -type d -name gcc           # Find only DIRECTORIES named gcc
find /usr -type f -name gcc           # Find only regular FILES named gcc
find / -size +10M                     # Find files larger than 10MB
find / -size 0                        # Find empty files
find / -mtime 3                       # Files modified 3 days ago
find / -user root                     # Files owned by root
find -name "*.jpg" -exec rm {} ';'   # Find and DELETE all .jpg files
find / -size +10M -exec command {} ';'  # Find large files and run command
Enter fullscreen mode Exit fullscreen mode

Key find Options:

Option Purpose
-name Match filename (case-sensitive)
-iname Match filename (case-insensitive)
-type f Regular files only
-type d Directories only
-size File size (+100M = over 100MB, -10k = under 10KB)
-mtime Modified time in days
-exec Execute a command on each result
-user Files owned by specific user

📝 NOTE: The {} is a placeholder filled with each file found. The ';' or \; terminates the -exec command.

The locate Command

locate zip         # Fast search using pre-built database
# Database is updated by 'updatedb' (runs daily automatically)
Enter fullscreen mode Exit fullscreen mode

which & whereis

which python3      # Shows path of executable: /usr/bin/python3
whereis python3    # Shows binary, source, and man page locations
Enter fullscreen mode Exit fullscreen mode

I/O Redirection & Pipes

echo "hello" > file.txt       # Redirect stdout to file (overwrite)
echo "world" >> file.txt      # Redirect stdout to file (append)
command < input.txt           # Feed file as stdin to command
command 2> errors.txt         # Redirect stderr to file
command > out.txt 2>&1        # Redirect BOTH stdout AND stderr to file
cat /etc/passwd | wc -l       # Pipe: send output of cat as input to wc
cat /etc/passwd | cut -d: -f1 | sort | uniq  # Chain multiple pipes
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: > overwrites, >> appends. 2>&1 redirects errors to same place as stdout. The pipe | chains commands together.

Process Management

kill -SIGKILL <PID>       # Force kill a process (same as kill -9)
kill -9 <PID>             # Force kill by PID
node server.js &          # Run process in background (& suffix)
lsof -i :80              # Find what process is using port 80
Enter fullscreen mode Exit fullscreen mode

📝 NOTE: You can only kill your own processes (unless you are root).

Getting Help

man apache2       # Full manual page for a command
man -k compress   # Search man pages by keyword
info make         # GNU Info documentation (alternative to man)
command --help    # Quick help/usage summary (fastest option)
Enter fullscreen mode Exit fullscreen mode

3. File Permissions & Ownership

Three Types of Owners

  • User (u): The owner of the file. When you create a file, you become the owner.
  • Group (g): A collection of users. Useful in multi-user environments.
  • Other (o): Everyone else on the system.

Three Types of Permissions

Permission Symbol Number On Files On Directories
Read r 4 View/copy file contents List directory contents (ls)
Write w 2 Modify file contents Create/delete files inside
Execute x 1 Run the file as program Enter the directory (cd)

Octal Permission Table (MEMORIZE THIS!)

Number 0 1 2 3 4 5 6 7
Permission --- --x -w- -wx r-- r-x rw- rwx
Meaning None Exec only Write only Write+Exec Read only Read+Exec Read+Write ALL

Reading Permission Strings

-rw-r--r-- 1 sajid devops_students 13 2022-05-11 08:29 lecture.txt
 ^^^^^^^^^   ^     ^
 |           |     +-- group owner
 |           +-------- file owner (user)
 +-------------------- permission string

First char: - = file, d = directory, l = symlink
Next 9 chars: rwx for user | rwx for group | rwx for others

Example: -rw-r--r-- means:
  User:  rw-  (read + write)      = 4+2+0 = 6
  Group: r--  (read only)          = 4+0+0 = 4
  Other: r--  (read only)          = 4+0+0 = 4
  Octal: 644
Enter fullscreen mode Exit fullscreen mode

chmod — Change Permissions

chmod 644 file.txt         # rw-r--r-- (standard file permission)
chmod 755 directory/       # rwxr-xr-x (standard directory permission)
chmod 700 secret.txt       # rwx------ (owner only, full access)
chmod 666 file.txt         # rw-rw-rw- (everyone can read/write)
chmod +x script.sh         # Add execute permission for everyone
chmod u+x script.sh        # Add execute for user only
chmod g-w file.txt         # Remove write from group
chmod o-rwx file.txt       # Remove all permissions from others
Enter fullscreen mode Exit fullscreen mode

chown — Change Ownership

sudo chown root:root file.txt           # Change owner AND group to root
sudo chown daniyal file.txt             # Change owner only
sudo chown daniyal:www-data file.txt    # Change owner to daniyal, group to www-data
sudo chown -R www-data:www-data /var/www/html/  # Recursive (all files inside)
Enter fullscreen mode Exit fullscreen mode

⭐ DevOps Golden Rules for Permissions

Rule Permission Why
Directories 755 (rwxr-xr-x) Owner full access, others can read/enter
Regular files 644 (rw-r--r--) Owner read/write, others read only
Scripts (.sh) 755 (rwxr-xr-x) Must be executable
SSH private key 600 (rw-------) ONLY owner can read (SSH refuses otherwise)
~/.ssh/ directory 700 (rwx------) ONLY owner can access
authorized_keys 600 (rw-------) ONLY owner can read/write
Web files owner www-data:www-data Web server user must be able to read
NEVER use 777 SECURITY RISK — everyone has full access!

🔥 EXAM TIP: If a web page shows '403 Forbidden', first check permissions and ownership! Owner should be www-data, dirs 755, files 644.


4. Users & Groups Management

User Management Commands

cat /etc/passwd                    # List ALL users on the system
sudo adduser newuser               # Create new user (interactive - sets password)
sudo useradd newuser               # Create user (non-interactive - no password set)
sudo usermod -aG sudo newuser      # Add user to sudo group (give admin rights)
sudo userdel newuser               # Delete a user
sudo userdel -r newuser            # Delete user AND their home directory
su - newuser                       # Switch to another user
whoami                             # Show current username
id                                 # Show user ID, group ID, and groups
Enter fullscreen mode Exit fullscreen mode

Group Management Commands

cat /etc/group                     # List all groups
sudo groupadd devopsgroup          # Create a new group
sudo usermod -aG devopsgroup user1 # Add user1 to devopsgroup
sudo groupdel devopsgroup          # Delete a group
groups username                    # Show which groups a user belongs to
Enter fullscreen mode Exit fullscreen mode

📝 NOTE: The -aG flag is critical! Without -a, the user gets REMOVED from all other groups. Always use -aG together.

Important Files

  • /etc/passwd — Contains user account info (username:x:UID:GID:info:home:shell)
  • /etc/shadow — Contains encrypted passwords (only root can read)
  • /etc/group — Contains group definitions

5. SSH (Secure Shell)

What is SSH?

SSH (Secure Shell) allows you to connect and log into remote systems securely. It encrypts ALL communication between client and server. SSH runs on port 22 by default. The server must have sshd (SSH daemon) installed and running.

Basic SSH Connection

ssh username@remote_server_ip       # Connect to remote machine
ssh daniyal@192.168.1.100           # Example with IP
whoami                               # Verify you are logged in
hostname                             # Verify which machine you are on
exit                                 # Disconnect from remote
Enter fullscreen mode Exit fullscreen mode

SSH Service Control

sudo systemctl status ssh          # Check if SSH is running
sudo systemctl start ssh           # Start SSH service
sudo systemctl stop ssh            # Stop SSH service
sudo systemctl restart ssh         # Restart (apply config changes)
sudo systemctl enable ssh          # Start automatically on boot
sudo systemctl disable ssh         # Don't start on boot
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: systemctl enable makes service start on boot. systemctl start starts it NOW. They are different! You often need BOTH.

SSH Configuration File

The main SSH server config file is: /etc/ssh/sshd_config

sudo nano /etc/ssh/sshd_config     # Edit SSH server configuration

# Key settings to know:
Port 22                            # Default SSH port
PermitRootLogin yes/no             # Allow/block root login via SSH
PasswordAuthentication yes/no      # Allow/block password-based login
PubkeyAuthentication yes           # Allow key-based authentication

# IMPORTANT: After ANY change, restart SSH!
sudo systemctl restart ssh
Enter fullscreen mode Exit fullscreen mode

SSH Key-Based Authentication

Key-based auth is more secure than passwords. It uses a pair of keys:

  • Private key (~/.ssh/id_rsa): Stays on YOUR machine. NEVER share this!
  • Public key (~/.ssh/id_rsa.pub): Goes to the REMOTE server.

Step-by-step setup:

# STEP 1: Generate key pair on YOUR machine (client)
ssh-keygen -t rsa
# Press Enter for default location (~/.ssh/id_rsa)
# Press Enter for no passphrase (or set one for extra security)
# Creates: ~/.ssh/id_rsa (private) and ~/.ssh/id_rsa.pub (public)

# STEP 2: Copy public key to the REMOTE server
ssh-copy-id username@remote_server
# OR manually:
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys  # On the remote server

# STEP 3: Set correct permissions (CRITICAL!)
chmod 700 ~/.ssh                   # Directory: owner only
chmod 600 ~/.ssh/id_rsa            # Private key: owner only
chmod 600 ~/.ssh/authorized_keys   # Auth keys: owner only

# STEP 4: Now you can login without password!
ssh username@remote_server
Enter fullscreen mode Exit fullscreen mode

📝 NOTE: The remote server stores public keys in ~/.ssh/authorized_keys (one key per line). If permissions on this file are wrong, SSH will REFUSE the key and fall back to password auth.

SSH Config File (Client Side)

Create ~/.ssh/config to avoid typing username and IP every time:

# File: ~/.ssh/config
Host myserver
    HostName 192.168.1.100
    User daniyal
    IdentityFile ~/.ssh/id_rsa

# Now you can just type:
ssh myserver
# Instead of: ssh daniyal@192.168.1.100
Enter fullscreen mode Exit fullscreen mode

Non-Interactive SSH Commands

Run commands on a remote server without opening a full session:

ssh user@server "whoami"                    # Run whoami on remote
ssh user@server "mkdir ~/test_dir"          # Create dir on remote
ssh user@server "cat /etc/hostname"         # Read remote file
ssh user@server "systemctl restart apache2" # Restart service remotely
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: Non-interactive SSH is key for scripting — you can loop over servers: for server in list; do ssh server "command"; done

Disabling Root Login & Password Auth

# Edit /etc/ssh/sshd_config:
PermitRootLogin no              # Block root from logging in via SSH
PasswordAuthentication no       # Force key-based auth only

# Restart to apply:
sudo systemctl restart ssh

# Test: trying ssh root@server should now be DENIED
Enter fullscreen mode Exit fullscreen mode

6. Apache Web Server

Installation & Service Management

sudo apt update
sudo apt install apache2           # Install Apache

sudo systemctl start apache2       # Start the service
sudo systemctl stop apache2        # Stop the service
sudo systemctl restart apache2     # Restart (apply changes)
sudo systemctl reload apache2      # Reload config without downtime
sudo systemctl status apache2      # Check if running
sudo systemctl enable apache2      # Start on boot

curl localhost                     # Test: should show Apache default page
Enter fullscreen mode Exit fullscreen mode

Apache runs on Port 80 (HTTP) or Port 443 (HTTPS)

Apache Default Paths

Path Purpose
/var/www/html/ Default web root (put your website files here)
/etc/apache2/ Main configuration directory
/etc/apache2/sites-available/ Virtual host config files (available)
/etc/apache2/sites-enabled/ Symlinks to active virtual hosts
/etc/apache2/apache2.conf Main Apache configuration file
/etc/apache2/ports.conf Which ports Apache listens on
/var/log/apache2/error.log Error log file
/var/log/apache2/access.log Access log file

Deploying a Static Website

# Step 1: Clone or copy your website files
sudo git clone https://github.com/user/repo.git /var/www/html/mysite

# Step 2: Set correct ownership
sudo chown -R www-data:www-data /var/www/html/mysite

# Step 3: Set correct permissions
sudo chmod -R 755 /var/www/html/mysite/                        # Directories
sudo find /var/www/html/mysite -type f -exec chmod 644 {} \;   # Files

# Step 4: Verify
curl localhost
Enter fullscreen mode Exit fullscreen mode

Virtual Hosts (Multiple Websites)

Virtual hosts let you run MULTIPLE websites on one server, each on a different port or domain.

# Step 1: Create config file in sites-available
sudo nano /etc/apache2/sites-available/mysite.conf
Enter fullscreen mode Exit fullscreen mode

Content of mysite.conf:

<VirtualHost *:8080>
    ServerName mysite.local
    DocumentRoot /var/www/mysite
    ErrorLog /var/log/apache2/mysite-error.log
    CustomLog /var/log/apache2/mysite-access.log combined
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode
# Step 2: Add Listen directive for new port
# Edit /etc/apache2/ports.conf and add: Listen 8080

# Step 3: Enable the site
sudo a2ensite mysite.conf

# Step 4: Test config and reload
sudo apache2ctl configtest         # Check for syntax errors
sudo systemctl reload apache2

# Step 5: Verify
curl localhost:8080
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: sites-available = config files stored here. sites-enabled = symlinks to active configs. Use a2ensite/a2dissite to enable/disable.


7. Nginx Web Server

Installation & Service Management

sudo apt update
sudo apt install nginx

sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl status nginx
sudo systemctl enable nginx

curl localhost                     # Test
Enter fullscreen mode Exit fullscreen mode

Nginx Key Paths

  • Default web root: /var/www/html/ (same as Apache)
  • Config files: /etc/nginx/sites-available/ and /etc/nginx/sites-enabled/
  • Main config: /etc/nginx/nginx.conf
  • Default site config: /etc/nginx/sites-available/default

Nginx Virtual Host (Server Block)

# File: /etc/nginx/sites-available/mysite
server {
    listen 80;
    server_name mysite.local;
    root /var/www/mysite;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
Enter fullscreen mode Exit fullscreen mode
# Enable the site by creating a symlink:
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/

# Test config:
sudo nginx -t

# Reload:
sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

📝 NOTE: Both Apache and Nginx use port 80 by default. They CANNOT run on the same port at the same time!


8. Port Debugging & Troubleshooting

Common Scenario: Port Conflict

If Apache fails to start with "Address already in use" error, another process (like Nginx) is already using port 80.

Debugging Commands

# Check what's using a specific port
sudo lsof -i :80                   # Show process using port 80

# Production-friendly command (all open network connections)
sudo lsof -i -P -n
# -i = open network connections
# -P = show port numbers (not service names)
# -n = don't resolve hostnames

# Check service logs for errors
sudo journalctl -xe                # Show recent system logs with details
sudo journalctl -u apache2         # Show only Apache logs

# Monitor log files in real-time
sudo tail -f /var/log/apache2/error.log
sudo tail -f /var/log/nginx/error.log
Enter fullscreen mode Exit fullscreen mode

Fixing Port Conflicts Step by Step

# Step 1: Check which service is using port 80
sudo lsof -i :80
# Output shows: nginx (PID 1234)

# Step 2: Stop the conflicting service
sudo systemctl stop nginx

# Step 3: Start the service you want
sudo systemctl start apache2

# Step 4: Verify
sudo systemctl status apache2
curl localhost
Enter fullscreen mode Exit fullscreen mode

Common Web Server Errors & Fixes

Error Likely Cause Fix
403 Forbidden Wrong permissions/ownership chown www-data:www-data, chmod 755/644
404 Not Found Wrong DocumentRoot path Check config file, verify path exists
Address in use Port conflict lsof -i :80, stop conflicting service
Service won't start Config syntax error apache2ctl configtest or nginx -t
Connection refused Service not running systemctl start apache2/nginx

9. Bash Scripting

Script Basics

#!/bin/bash
# The first line is the SHEBANG — tells the system to use bash
# Every script MUST start with #!/bin/bash

# Make script executable:
chmod +x script.sh

# Run script:
./script.sh
# OR
bash script.sh
Enter fullscreen mode Exit fullscreen mode

Variables

#!/bin/bash
NAME="Daniyal"                     # Assign (NO spaces around =)
echo "Hello $NAME"                 # Use variable with $
echo "Hello ${NAME}"               # Curly braces version (safer)

# Read user input
echo "Enter your name:"
read USERNAME                      # Stores input in USERNAME
echo "Welcome $USERNAME"

# Command substitution — store command output in variable
TODAY=$(date)                      # Run date command, store result
echo "Today is: $TODAY"

HOSTNAME=$(hostname)
echo "Machine: $HOSTNAME"
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: NO SPACES around = when assigning variables! NAME='value' is correct. NAME = 'value' is WRONG and will cause an error.

Command Line Arguments

Variable Meaning
$0 Script name itself
$1, $2, $3... First, second, third argument...
$# Total number of arguments passed
$@ All arguments as separate words
$? Exit code of the LAST command (0=success, non-0=failure)
#!/bin/bash
# Example: ./myscript.sh hello world
echo "Script name: $0"            # ./myscript.sh
echo "First arg: $1"              # hello
echo "Second arg: $2"             # world
echo "Total args: $#"             # 2
echo "All args: $@"               # hello world
Enter fullscreen mode Exit fullscreen mode

Exit Codes

#!/bin/bash
# Every command returns an exit code
# 0 = SUCCESS, anything else = FAILURE

ls /tmp
echo $?    # 0 (success — /tmp exists)

ls /nonexistent
echo $?    # 2 (failure — directory doesn't exist)

# Set your own exit code
exit 0     # Exit script with success
exit 1     # Exit script with failure
Enter fullscreen mode Exit fullscreen mode

Conditionals (if/else)

#!/bin/bash
# Basic if/else
if [ -d "/var/www/html" ]; then
    echo "Directory exists"
else
    echo "Directory does NOT exist"
fi

# Check if file exists
if [ -f "/etc/ssh/sshd_config" ]; then
    echo "SSH config found"
fi

# Compare strings
if [ "$1" == "install" ]; then
    echo "Installing..."
elif [ "$1" == "remove" ]; then
    echo "Removing..."
else
    echo "Usage: $0 install|remove"
    exit 1
fi

# Check if command succeeded
apt install nginx -y
if [ $? -eq 0 ]; then
    echo "Installation successful"
else
    echo "Installation FAILED"
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Common test operators:

Operator Meaning
-f file File exists and is a regular file
-d dir Directory exists
-e path Path exists (file or directory)
-z string String is empty (zero length)
-n string String is NOT empty
str1 == str2 Strings are equal
str1 != str2 Strings are NOT equal
num1 -eq num2 Numbers are equal
num1 -ne num2 Numbers are NOT equal
num1 -gt num2 Greater than
num1 -lt num2 Less than

Case Statement (for Flags)

#!/bin/bash
# Great for handling command-line flags like -i, -r, -h
case "$1" in
    -i|--install)
        echo "Installing..."
        ;;
    -r|--remove)
        echo "Removing..."
        ;;
    -h|--help)
        echo "Usage: $0 [-i install] [-r remove] [-h help]"
        ;;
    *)
        echo "Invalid option: $1"
        echo "Use -h for help"
        exit 1
        ;;
esac
Enter fullscreen mode Exit fullscreen mode

For Loops

#!/bin/bash
# Loop through a list
for server in server1 server2 server3; do
    echo "Restarting $server..."
    ssh $server "systemctl restart apache2"
done

# Loop through files
for file in *.sh; do
    echo "Found script: $file"
done

# Loop with numbers
for i in 1 2 3 4 5; do
    echo "Number: $i"
done

# C-style loop
for ((i=1; i<=5; i++)); do
    echo "Count: $i"
done
Enter fullscreen mode Exit fullscreen mode

The tar Command (Archives/Backups)

# Create a compressed archive
tar -czf backup.tar.gz /path/to/directory
# -c = create
# -z = compress with gzip
# -f = filename follows

# Create with timestamp in name
tar -czf backup_$(date +%Y%m%d_%H%M%S).tar.gz /var/www/html/

# Extract an archive
tar -xzf backup.tar.gz
# -x = extract

# List contents without extracting
tar -tzf backup.tar.gz
Enter fullscreen mode Exit fullscreen mode

The awk Command

# awk processes text line by line, splitting into fields
# Default field separator is whitespace

# Print second column of output
df -h | awk '{print $2}'

# Print specific fields with custom format
free -m | awk '/Mem:/ {print "Total: "$2" MB, Used: "$3" MB"}'

# Use custom field separator
cat /etc/passwd | awk -F: '{print $1}'   # Print usernames (field 1, : separator)

# Filter lines matching a pattern
df -h | awk '!/tmpfs/ {print $0}'        # Exclude lines containing tmpfs
Enter fullscreen mode Exit fullscreen mode

Heredoc (Writing Multi-line Content)

#!/bin/bash
# Heredoc writes multi-line content to a file
cat << EOF > /var/www/html/index.html
<!DOCTYPE html>
<html>
<head><title>System Report</title></head>
<body>
    <h1>Server: $(hostname)</h1>
    <p>Date: $(date)</p>
</body>
</html>
EOF
# Variables inside heredoc get expanded!
# Use << 'EOF' (with quotes) to PREVENT variable expansion
Enter fullscreen mode Exit fullscreen mode

Redirection in Scripts

#!/bin/bash
# Redirect command output to log file
apt install nginx -y > nginx.log 2>&1
# > nginx.log    = redirect stdout to file
# 2>&1           = redirect stderr (2) to same place as stdout (1)
# Combined: ALL output (normal + errors) goes to nginx.log

# Append to log
echo "$(date) - Installation complete" >> nginx.log
Enter fullscreen mode Exit fullscreen mode

Lab Script Examples

Script 1: backup.sh — Automated Directory Backup

#!/bin/bash
echo "Enter directory path to backup:"
read DIR_PATH

if [ ! -d "$DIR_PATH" ]; then
    echo "ERROR: Directory $DIR_PATH does not exist!"
    exit 1
fi

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="backup_${TIMESTAMP}.tar.gz"

tar -czf "$BACKUP_FILE" "$DIR_PATH"

if [ $? -eq 0 ]; then
    echo "SUCCESS: Backup created: $BACKUP_FILE"
    echo "$(date) - SUCCESS - $BACKUP_FILE" >> backup.log
else
    echo "FAILED: Backup failed!"
    echo "$(date) - FAILED" >> backup.log
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Script 2: Virtual Host Automator

#!/bin/bash
echo "Enter domain/directory name:"
read DOMAIN

sudo mkdir -p /var/www/$DOMAIN

sudo cat << EOF > /var/www/$DOMAIN/index.html
<html><body><h1>Welcome to $DOMAIN</h1></body></html>
EOF

sudo cat << EOF > /etc/apache2/sites-available/$DOMAIN.conf
<VirtualHost *:80>
    ServerName $DOMAIN
    DocumentRoot /var/www/$DOMAIN
    ErrorLog /var/log/apache2/${DOMAIN}-error.log
    CustomLog /var/log/apache2/${DOMAIN}-access.log combined
</VirtualHost>
EOF

sudo chown -R www-data:www-data /var/www/$DOMAIN
sudo chmod -R 755 /var/www/$DOMAIN
sudo a2ensite $DOMAIN.conf
sudo systemctl reload apache2
echo "Website $DOMAIN deployed successfully!"
Enter fullscreen mode Exit fullscreen mode

Script 3: wserver.sh — Nginx Install/Remove with Flags

#!/bin/bash
case "$1" in
    -i)
        if dpkg -l | grep -q nginx; then
            echo "Nginx is already installed."
            exit 0
        fi
        sudo apt install nginx -y > nginx.log 2>&1
        if [ $? -eq 0 ]; then
            echo "Nginx installed successfully."
        else
            echo "ERROR: Installation failed. Check nginx.log"
            exit 1
        fi
        ;;
    -r)
        if ! dpkg -l | grep -q nginx; then
            echo "Nginx is not installed."
            exit 0
        fi
        sudo apt remove nginx -y > nginx.log 2>&1
        if [ $? -eq 0 ]; then
            echo "Nginx removed successfully."
        else
            echo "ERROR: Removal failed. Check nginx.log"
            exit 1
        fi
        ;;
    *)
        echo "Usage: $0 [-i install] [-r remove]"
        exit 1
        ;;
esac
Enter fullscreen mode Exit fullscreen mode

Script 4: system_health.sh — HTML Report

#!/bin/bash
TOTAL_MEM=$(free -m | awk '/Mem:/ {print $2}')
USED_MEM=$(free -m | awk '/Mem:/ {print $3}')
AVAIL_MEM=$(free -m | awk '/Mem:/ {print $7}')
TOTAL_SWAP=$(free -m | awk '/Swap:/ {print $2}')
USED_SWAP=$(free -m | awk '/Swap:/ {print $3}')

DISK_TOTAL=$(df -h --total --exclude-type=tmpfs | awk '/total/ {print $2}')
DISK_USED=$(df -h --total --exclude-type=tmpfs | awk '/total/ {print $3}')
DISK_AVAIL=$(df -h --total --exclude-type=tmpfs | awk '/total/ {print $4}')

cat << EOF > system_health.html
<!DOCTYPE html>
<html>
<head><title>System Health Report</title></head>
<body>
<h1>System Health Report</h1>
<p>Date: $(date)</p>
<h2>Memory Usage</h2>
<p>Total: ${TOTAL_MEM}MB | Used: ${USED_MEM}MB | Available: ${AVAIL_MEM}MB</p>
<h2>Disk Usage</h2>
<p>Total: $DISK_TOTAL | Used: $DISK_USED | Available: $DISK_AVAIL</p>
</body>
</html>
EOF

sudo cp system_health.html /var/www/html/index.html
if [ $? -eq 0 ]; then
    echo "SUCCESS: Report hosted at http://localhost"
else
    echo "ERROR: Failed to deploy report"
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Script 5: systeminfo.sh

#!/bin/bash
echo "Kernel Name: $(uname -s)"
echo "Kernel Release: $(uname -r)"
echo "Processor: $(uname -p)"
echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)"

EDITOR="nano"
echo "Favorite Editor: $EDITOR"
echo "Editor Location: $(which $EDITOR)"
echo "Documentation: $(whereis $EDITOR)"
Enter fullscreen mode Exit fullscreen mode

10. Docker Containers

What is Docker?

Docker is a platform that lets you package, ship, and run applications in isolated environments called containers. A container is like a lightweight virtual machine that shares the host OS kernel. Think of it as: your app + all its dependencies, packaged together so it runs the same everywhere.

Key Concepts

  • Image: A blueprint/template for a container (like a class in OOP). Downloaded from Docker Hub.
  • Container: A running instance of an image (like an object). You can run multiple from one image.
  • Docker Hub: Online registry of Docker images (like GitHub for images).
  • Tag: Version of an image. Example: ubuntu:22.04 vs ubuntu:latest

Verify Docker Installation

docker --version           # Check Docker version
docker version             # Detailed client + server version
docker run hello-world     # Test Docker works
Enter fullscreen mode Exit fullscreen mode

Docker Container Lifecycle

# PULL an image from Docker Hub
docker pull ubuntu                 # Download ubuntu image (latest)
docker pull ubuntu:22.04           # Download specific version
docker pull nginx                  # Download nginx image

# RUN a container from an image
docker run ubuntu                  # Runs and exits immediately (no process)
docker run ubuntu sleep 5          # Runs, sleeps 5 seconds, then exits

# RUN in interactive mode (get a shell inside container)
docker run -it ubuntu bash         # -i=interactive, -t=terminal
# You are now INSIDE the container!
echo "Hello Docker"
ls
exit                               # Exit container (container stops)

# RUN with a custom name
docker run --name myubuntu ubuntu sleep 30

# RUN in detached mode (background)
docker run -d ubuntu sleep 300     # -d = detached (runs in background)
docker run -dit --name test ubuntu bash  # Detached + interactive
Enter fullscreen mode Exit fullscreen mode

Managing Containers

# LIST containers
docker ps                          # Show RUNNING containers only
docker ps -a                       # Show ALL containers (running + stopped)

# STOP a container
docker stop <container_id>         # Graceful stop
docker stop myubuntu               # Stop by name

# REMOVE a container
docker rm <container_id>           # Remove stopped container
docker rm myubuntu                 # Remove by name

# STOP ALL containers at once
docker stop $(docker ps -q)        # -q = quiet (only IDs)

# REMOVE ALL containers
docker rm $(docker ps -aq)         # Remove all (running + stopped)
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: docker run ubuntu exits immediately because there is no long-running process. Use sleep, -it bash, or -d to keep it alive.

Managing Images

# LIST downloaded images
docker images

# REMOVE an image
docker rmi ubuntu                  # Remove ubuntu image
docker rmi <image_id>              # Remove by ID
# Note: Must remove all containers using that image first!
Enter fullscreen mode Exit fullscreen mode

Attach vs Exec (IMPORTANT DIFFERENCE!)

# ATTACH to a running container (connects to main process)
docker attach test
# CTRL+P then CTRL+Q = detach WITHOUT stopping container
# If you type 'exit', container STOPS

# EXEC runs a NEW process inside a running container
docker exec -it test bash
# If you type 'exit', only the exec process ends
# The container keeps running!
Enter fullscreen mode Exit fullscreen mode

📝 NOTE: Use exec when you want to inspect a running container without affecting it. Use attach to reconnect to the main process.

Container Logs & Inspect

docker logs <container_id>                          # View container logs
docker logs myubuntu

docker inspect test                                  # Full container details (JSON)
docker inspect --format='{{.State.Status}}' test     # Get specific info
Enter fullscreen mode Exit fullscreen mode

Port Mapping (-p)

Port mapping connects a port on your HOST machine to a port inside the container.

# Map host port 8081 to container port 80
docker run -d -p 8081:80 nginx
#                ^     ^
#                |     +-- container port (nginx listens on 80)
#                +-------- host port (access via localhost:8081)

# Run multiple web servers on different ports
docker run -d --name web1 -p 8081:80 ubuntu/apache2
docker run -d --name web2 -p 8082:80 ubuntu/apache2

# Access in browser:
# http://localhost:8081  -->  web1
# http://localhost:8082  -->  web2
Enter fullscreen mode Exit fullscreen mode

🔥 EXAM TIP: Format is -p HOST_PORT:CONTAINER_PORT. The HOST port is what you type in the browser. The CONTAINER port is what the app listens on inside.

Volume Mounts (-v) / Bind Mounts

Volumes let you share files between your host machine and the container.

# Mount current directory into container
docker run -it -v $(pwd):/scripts ubuntu bash
# $(pwd) = your current directory on host
# /scripts = path inside the container

# Mount a specific file into nginx
echo '<h1>Hello Docker!</h1>' > index.html
docker run -d -p 8081:80 -v $(pwd)/index.html:/usr/share/nginx/html/index.html nginx
# You have just hosted a simple web app!

# Mount a Python script
echo 'print("Hello, world!")' > hello.py
docker run -it --rm -v $(pwd)/hello.py:/hello.py python:3.10-slim bash
# Then inside: python hello.py
Enter fullscreen mode Exit fullscreen mode

📝 NOTE: The --rm flag automatically removes the container when it exits. Great for temporary containers.

Complete Docker Command Reference

Command Purpose
docker version Check Docker client and server version
docker run <image> Start a container from an image
docker run --name <n> <img> Run with a custom name
docker run <img>:<tag> Run a specific version
docker run -it <img> bash Run interactively with terminal
docker run -d <img> Run in detached (background) mode
docker run -p H:C <img> Map host port H to container port C
docker run -v H:C <img> Mount host path H to container path C
docker run --rm <img> Auto-remove container on exit
docker ps List running containers
docker ps -a List ALL containers
docker stop <id/name> Stop a running container
docker rm <id/name> Remove a stopped container
docker images List downloaded images
docker rmi <image> Remove an image
docker pull <image> Download image from Docker Hub
docker exec -it <id> bash Open shell in running container
docker attach <id> Attach to main process of container
docker logs <id> View container output logs
docker inspect <id> Detailed container info (JSON)
docker stop $(docker ps -q) Stop ALL running containers
docker rm $(docker ps -aq) Remove ALL containers

— list, create, add to sudo, switch user, create group

12. Quick Reference Cheat Sheet

systemctl Commands

systemctl start <service>     # Start a service NOW
systemctl stop <service>      # Stop a service NOW
systemctl restart <service>   # Restart a service
systemctl reload <service>    # Reload config without stopping
systemctl status <service>    # Check if service is running
systemctl enable <service>    # Start on boot
systemctl disable <service>   # Don't start on boot
Enter fullscreen mode Exit fullscreen mode

Key File Paths

Path What
/etc/ssh/sshd_config SSH server configuration
~/.ssh/id_rsa Your SSH private key
~/.ssh/id_rsa.pub Your SSH public key
~/.ssh/authorized_keys Public keys allowed to login
~/.ssh/config Client SSH shortcuts
/var/www/html/ Default web root (Apache + Nginx)
/etc/apache2/sites-available/ Apache virtual host configs
/etc/apache2/sites-enabled/ Active Apache sites (symlinks)
/etc/nginx/sites-available/ Nginx server block configs
/etc/nginx/sites-enabled/ Active Nginx sites (symlinks)
/var/log/apache2/error.log Apache error log
/var/log/nginx/error.log Nginx error log
/etc/passwd User account information
/etc/group Group definitions
/etc/shadow Encrypted passwords (root only)

Permission Quick Reference

644 = rw-r--r--   # Standard file permission
755 = rwxr-xr-x   # Standard directory / script permission
700 = rwx------   # Private (owner only)
600 = rw-------   # SSH keys
777 = rwxrwxrwx   # NEVER USE (security risk)
Enter fullscreen mode Exit fullscreen mode

Docker Quick Reference

docker run -it ubuntu bash        # Interactive shell
docker run -d -p 8080:80 nginx    # Background + port map
docker run -v $(pwd):/app ubuntu  # Volume mount
docker ps -a                      # List all containers
docker stop $(docker ps -q)       # Stop all running
docker rm $(docker ps -aq)        # Remove all containers
docker exec -it <id> bash         # Shell into running container
CTRL+P then CTRL+Q               # Detach without stopping
Enter fullscreen mode Exit fullscreen mode

Bash Scripting Quick Reference

#!/bin/bash                        # Shebang (always first line)
$1 $2 $# $@ $?                    # Args, count, all, exit code
read VAR                           # Read user input
if [ condition ]; then ... fi      # Conditional
case "$1" in pattern) ... ;; esac  # Flag handling
for item in list; do ... done      # Loop
tar -czf name.tar.gz dir/         # Create archive
awk '{print $1}' file             # Text processing
cat << EOF > file ... EOF          # Heredoc
command > file 2>&1               # Redirect all output
Enter fullscreen mode Exit fullscreen mode

Good luck on your exam! Practice these commands in the terminal — reading is not enough, you need muscle memory! 🚀

Top comments (0)