Skip to content

15 Must-Know Terminal Commands Every Developer Should Master (2026)

DodaTech Updated 2026-06-23 20 min read

In this tutorial, you'll learn about 15 must. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The terminal is the developer's most powerful tool, and mastering it separates developers who navigate their machine efficiently from those who fight it. Every operation — file navigation, text processing, Process management, network diagnostics, and system monitoring — can be done faster in the terminal than in any GUI. This guide covers 15 terminal commands that every developer should know by heart, not obscure flags for edge cases but the core commands that solve real problems daily.

In this guide, you will learn each command's primary use case, the most common flags and patterns, and how to combine commands into pipelines that solve complex problems. Every command includes examples you can run immediately with expected output shown. By the end, you will have a mental toolkit that replaces clicking through file managers, scrolling through log files, and manually restarting servers.

File Navigation and Inspection

ls — List directory contents with options for detailed views.

The most basic file listing command. Used with -l for long format (permissions, owner, size, date), -a to show hidden files (those starting with a dot, like .git and .env), -h for human-readable sizes, -t to sort by modification time, and -S to sort by size. Combine as ls -lart to see all files sorted by recency in long format. Alias ls to ls -Fh --color=auto for file type indicators and colorized output.

# Show all files with details, sorted by newest first
ls -lart

# Show only directories in the current path
ls -d */

# Show files sorted by size, largest last
ls -lASh

The -l output format shows -rw-r--r-- (permissions), number of hard links, owner, group, file size, modification date, and filename. The first character indicates file type: - for regular file, d for directory, l for symbolic link, p for named pipe, s for socket.

Why it matters: ls is the first command you type when exploring any directory. Knowing its options means you find files by recency, check permissions before deployment, and inspect file sizes without opening a file manager. The -l flag is essential for verifying ownership and permissions in multi-user environments.

cd — Change directory with shortcut conventions.

cd navigates the filesystem. Use cd - to toggle back to the previous directory, cd ~ or cd alone to go home, cd .. to go up one level, cd ../.. to go up two levels, and cd / to go to the root directory. Tab completion (built into Bash and Zsh) shows available directories as you type.

# Toggle between two directories
cd /var/log/nginx
cd -   # back to previous directory
cd -   # back to /var/log/nginx

# Navigate to a sibling directory
cd ../apache2

# Go home from anywhere
cd ~

Shell-specific enhancements improve cd further. Zsh with setopt autocd lets you change to a directory by typing its path without the cd command. Tools like zoxide or autojump learn your most-used directories and let you jump to them with a fuzzy match: z proj takes you to /home/user/projects/website/ if that is your most-used match for "proj".

Why it matters: Efficient directory navigation is foundational to terminal productivity. The cd - shortcut alone saves dozens of seconds per day compared to retyping long paths. Mastery of cd means you never reach for the file manager for navigation.

pwd — Print working directory to show your current location.

pwd outputs the absolute path of the current directory. Use pwd -P to resolve symlinks and show the physical path (important when you have navigated through a symlink and want to know where you actually are in the filesystem). Essential in scripts that need to reference the current location.

# Show current directory
pwd
# Output: /home/user/projects/website

# Show physical path through a symlink
cd /var/www  # this might be a symlink to /home/user/sites/www
pwd -P       # shows /home/user/sites/www

Why it matters: Getting lost in the filesystem is common when jumping between projects. pwd tells you exactly where you are. Scripts use $(pwd) to construct absolute paths relative to the current location, which prevents errors from relative path assumptions when scripts are called from different directories.

Text Processing

grep — Search text patterns in files and command output.

grep searches for patterns using regular expressions. Use -i for case-insensitive, -r for recursive (searches subdirectories), -n for line numbers, -l to list only matching filenames (not the matching lines), -c to count matches per file, and -v to invert the match (show lines that do NOT match). The -E flag enables extended regular expressions for more complex patterns.

# Find all TODO comments recursively, case-insensitive
grep -rin "todo" src/

# Show files containing "FIXME" (not the matching lines)
grep -rl "FIXME" src/

# Count how many times ERROR appears in each log file
grep -c "ERROR" *.log

# Exclude lines containing "deprecated"
grep -v "deprecated" src/config.js

grep shines in pipelines. Pipe the output of any command into grep to filter results. ps aux | grep nginx shows only nginx-related processes. history | grep docker shows only Docker commands you have run. dmesg | grep -i error shows only kernel error messages.

Why it matters: grep is the universal text search tool. Every developer needs to find code, inspect logs, and filter command output multiple times per day. grep does this faster than any IDE search, works over SSH, and combines with other commands in pipelines.

sed — Stream editor for text transformation.

sed applies text transformations line by line. The most common pattern is sed 's/find/replace/flags' for search and replace. Use -i for in-place editing (back up with -i.bak to create filename.bak before modifying), -n with p for printing specific lines, and line ranges like '5,10d' to delete lines 5 through 10.

# Replace all occurrences of "foo" with "bar" (in-place with backup)
sed -i.bak 's/foo/bar/g' config.txt

# Print lines 20-30 of a file
sed -n '20,30p' large-log.txt

# Delete lines containing "DEBUG" (in-place)
sed -i '/DEBUG/d' app.log

# Replace only on lines matching a pattern
sed '/^#/ s/foo/bar/' config.txt

The substitution command syntax breaks down as: s (substitute command), /find/ (pattern to find), /replace/ (replacement text), g (global flag — replace all occurrences on each line, not just the first). Without g, only the first occurrence per line is replaced.

Why it matters: When you need to transform a thousand-line file, sed is irreplaceable. It handles log reformatting, configuration file updates, and bulk renaming inside files. The in-place flag is dangerous but essential — always use the backup extension until you are confident in the regex.

awk — Pattern scanning and text processing language.

awk processes structured text, splitting each line into fields ($1, $2, etc.) and applying patterns and actions. Use awk '{print $1, $3}' to extract specific columns, awk -F',' to set a custom field separator (comma for CSV), and awk '/pattern/ {action}' to apply actions conditionally.

# Print the second column of a space-separated log
awk '{print $2}' server.log

# Sum all values in the third column of a CSV
awk -F',' '{sum += $3} END {print sum}' data.csv

# Print lines where column 4 exceeds 1000
awk '$4 > 1000' server.log

# Format output with printf
awk '{printf "%-20s %8d\n", $1, $5}' server.log

The BEGIN block runs before processing any input (useful for headers). The END block runs after all input is processed (useful for totals). awk also supports associative arrays, which makes it capable of implementing hash-based aggregations that would require a full programming language in other tools.

Why it matters: awk is the go-to tool for column-based data processing. When you need to extract, aggregate, or reformat structured log data, awk does it in a single line that runs faster than any equivalent Python script. It is particularly useful for processing server logs, CSV files, and system command output.

Process Management

ps — Snapshot of current processes with detailed information.

ps shows running processes. Use ps aux for a complete list with user, CPU, memory, VSZ, RSS, TTY, STAT, START, TIME, and COMMAND columns. ps aux --sort=-%mem sorts by memory usage (descending). ps aux --sort=-%cpu sorts by CPU usage. ps -ef provides a similar full-format listing. ps -u username shows processes for a specific user.

# Show top 10 memory-consuming processes
ps aux --sort=-%mem | head -11

# Find the PID of a specific process
ps aux | grep nginx

# Show process tree for a specific PID
ps -ef --forest | grep -A5 nginx

# Show all processes owned by www-data
ps -u www-data -f

The STAT column shows the Process state: R (running), S (sleeping), D (uninterruptible sleep, often waiting for I/O), Z (zombie, Process completed but not reaped by parent), T (stopped by signal). A Process in state D for an extended time may indicate a storage or network issue.

Why it matters: When an application hangs, a Process eats 100 percent CPU, or you need to find a PID to kill or signal a Process, ps is the tool. It is the starting point for all Process troubleshooting and pairs with kill, top, and lsof for complete Process management.

top — Real-time Process monitoring with dynamic updates.

top displays processes in real time sorted by CPU usage. Press M to sort by memory, P to sort by CPU, k to kill a Process (you are prompted for PID and signal), r to renice a Process, 1 to toggle per-CPU display, and q to quit. The header shows system summary: load average (1, 5, 15 minute averages), task count, CPU usage breakdown (us, sy, ni, id, wa, hi, si, st), and memory usage.

# Launch top with default view
top

# Launch top sorted by memory immediately
top -o %MEM

# Show only processes owned by a specific user
top -u www-data

htop is a modern alternative with color output, mouse support, tree view, and easier navigation. Install it with your package manager: sudo apt install htop or brew install htop. The tree view (F5) shows the parent-child relationship between processes.

Why it matters: When your system slows down, top identifies the culprit in seconds. It shows which Process is consuming CPU or memory, what the overall system load is, and how much memory is available. This is the first diagnostic step for any performance issue.

kill — Send signals to processes by PID.

kill sends POSIX signals to processes. Common signals: SIGTERM (15, graceful shutdown, default), SIGKILL (9, forced termination, cannot be caught or ignored), SIGHUP (1, hang up, often causes daemons to reload configuration), SIGINT (2, interrupt, same as Ctrl+C), SIGSTOP (19, pause execution), SIGCONT (18, resume execution). Use kill -l to list all signals.

# Gracefully stop a process by PID (SIGTERM)
kill 1234

# Force kill a stuck process (SIGKILL) — last resort only
kill -9 1234

# Stop all nginx processes by name
pkill nginx

# Send SIGHUP to reload nginx configuration
kill -1 $(pgrep nginx | head -1)

Always try SIGTERM first. A well-behaved application catches SIGTERM, cleans up resources (closes files, flushes buffers, releases locks), and exits gracefully. Only use SIGKILL when a Process ignores SIGTERM or is causing system instability. SIGKILL terminates immediately at the kernel level with no cleanup possible, which can leave behind corrupted files or orphaned resources.

Why it matters: Every developer needs to stop processes — stuck servers, runaway scripts, orphaned Background Jobs. Graceful termination (SIGTERM) allows cleanup. Force kill (SIGKILL) is the last resort. Knowing the difference prevents data corruption and resource leaks.

Network Diagnostics

curl — Transfer data to or from a server, supporting HTTP, HTTPS, FTP, and more.

curl is the universal HTTP client for the terminal. Use curl URL for a GET request, curl -X POST -d 'data' URL for POST, curl -I URL for headers only (no response body), curl -v URL for verbose output with request and response details including SSL certificate info, curl -o file URL to save output, curl -L URL to follow redirects, curl -H "Header: value" URL for custom headers.

# Check HTTP response headers (useful for debugging CORS, caching, auth)
curl -I https://api.example.com

# POST JSON data to an API
curl -X POST https://api.example.com/data \
  -H "Content-Type: application/json" \
  -d '{"key": "value"}'

# Download a file with progress bar
curl -o file.zip -L https://example.com/download/file.zip

# Check SSL certificate details
curl -vI https://example.com 2>&1 | grep -i "ssl\|certificate"

The verbose output shows every step: DNS resolution, TCP connection, TLS handshake, request headers sent, response headers received, and response body. When debugging API calls, curl -v reveals authentication issues, redirect loops, and header mismatches that browser dev tools might hide.

Why it matters: curl is the Swiss Army knife of HTTP debugging. Before writing code that calls an API, verify the endpoint with curl. When debugging authentication, use curl with -v to see the full request and response. When checking if a server is running, curl the health endpoint. It works in scripts, over SSH, and on minimal containers.

ping — Test network connectivity and measure round-trip time.

ping sends ICMP echo requests to a host and reports response times and packet loss. Use ping -c 4 host to limit to 4 packets, ping -i 2 to set 2-second interval, ping -t 64 to set TTL, ping -D host to include timestamps, and ping -s 1472 to set packet size (useful for testing MTU issues).

# Send 4 pings to check connectivity
ping -c 4 google.com

# Continuous ping with timestamps (monitoring mode)
ping -D google.com

# Test with specific packet size (1472 = typical MTU minus headers)
ping -c 4 -s 1472 example.com

The output shows sequence numbers, TTL, round-trip time per packet, and summary statistics: packets transmitted, received, packet loss percentage, and min/avg/max/stddev round-trip times. 0 percent packet loss with consistent latency means the network path is healthy. Packet loss above 1 percent indicates network issues.

Why it matters: When your app cannot connect to a database, API, or service, ping tells you whether the host is reachable at the network level. No ping response means the problem is network infrastructure, not application code. This eliminates an entire category of debugging before you even look at logs.

ss — Socket statistics for investigating network connections.

ss replaces the deprecated netstat. Use ss -tuln to show listening TCP and UDP ports with numeric addresses, ss -tap to show all TCP connections with the associated Process, ss -s for summary statistics, ss -t state established for only established connections, and ss -tunap to show everything (TCP, UDP, numeric, all states, processes).

# Show all listening ports and which processes own them
ss -tulpn

# Show all established TCP connections
ss -t state established

# Show connections to a specific port
ss -tunap | grep :443

# Summary statistics
ss -s

The output shows local and remote addresses, port numbers, connection state (LISTEN, ESTABLISHED, TIME_WAIT, CLOSE_WAIT), and Process information when run with -p. A large number of connections in TIME_WAIT is normal for high-traffic servers. Connections stuck in CLOSE_WAIT indicate the application is not properly closing sockets.

Why it matters: When a port is already in use and your application refuses to start, ss tells you which Process is holding the port. When diagnosing connection limits or unexpected connections, ss shows the full connection table. This is the essential tool for port conflict and connection troubleshooting.

System Monitoring

df — Report filesystem disk space usage.

df shows mounted filesystems, total space, used space, available space, and usage percentage. Use df -h for human-readable sizes (GB, MB), df -T to show filesystem type, df -i to show inode usage instead of block usage (important when a filesystem has space but cannot create new files because inodes are exhausted), df -t ext4 to show only ext4 filesystems.

# Show disk usage in human-readable format
df -h

# Show disk usage for ext4 filesystems only
df -t ext4 -h

# Show inode usage
df -i

# Show with filesystem type column
df -hT

The output columns: Filesystem (device or remote mount), Size, Used, Avail, Use%, Mounted on. An Use% of 100 percent will cause write failures for any Process that tries to create or modify files. The Avail column shows space available to unprivileged users (by default, 5 percent of blocks are reserved for root).

Why it matters: Disk full errors are among the most common production outages. df tells you how much space is left on each mount point in seconds. The -h flag makes the output readable. Pair with du -sh * to find what is consuming space when a volume fills up.

du — Estimate file and directory space usage.

du reports disk usage for files and directories. Use du -sh * for a human-readable summary of each item in the current directory, du -sh . for the total of the current directory, du -h --max-depth=1 to limit subdirectory depth, du -sh * | sort -rh to sort by size, and du -sh --exclude=node_modules * to exclude large dependency directories.

# Show the largest directories in the current directory
du -sh * | sort -rh | head -10

# Total size of a specific directory
du -sh /var/log

# Show disk usage per subdirectory, one level deep
du -h --max-depth=1 /var

# Exclude node_modules for faster scans
du -sh --exclude=node_modules * | sort -rh | head -10

The difference between du and ls -l for directory sizes: ls shows the directory entry size (usually 4K for directories), while du recursively sums the sizes of all files and subdirectories inside. Use du --apparent-size to show logical sizes (as reported by ls) instead of disk usage, which accounts for filesystem block size overhead and sparse files.

Why it matters: When disk space is low, du identifies exactly which directories and files are consuming it. The combination of du with sort and head is the universal disk cleanup workflow. Understanding du output prevents accidental deletion of important files by confirming sizes before cleanup.

dmesg — Print kernel ring buffer messages for system diagnostics.

dmesg shows kernel messages including hardware detection, driver loading, filesystem errors, OOM killer activity, and device attachment events. Use dmesg -H for human-readable timestamps, dmesg -w to follow new messages in real time (like tail -f but for kernel messages), dmesg | tail -50 for the most recent messages, and dmesg --level=err,warn to show only errors and warnings.

# Show the last 20 kernel messages with timestamps
dmesg -H | tail -20

# Watch kernel messages in real time while reproducing an issue
sudo dmesg -w

# Show only errors and warnings
dmesg --level=err,warn -H

# Show messages related to USB devices
dmesg -H | grep -i usb

The OOM killer messages are especially important: they show which Process was killed, the system memory state at the time, and the total memory requested. If you see OOM killer messages, your application is exceeding available memory or there is a memory leak.

Why it matters: When hardware is not detected, a USB device is unresponsive, or the kernel kills processes due to out-of-memory conditions, dmesg has the answer. Application-level debugging often misses kernel-level issues. Checking dmesg when something unexpected happens can reveal hardware failures, driver issues, or memory pressure that no application log captures.

Challenge: Build a Log Analysis Pipeline

Combine grep, awk, sed, and sort to analyze a web server access log. Extract all 500 Internal Server Error responses, group them by URL path, sort by frequency, and output a report showing the 10 most error-prone endpoints.

# Analyze error-prone endpoints from nginx access log
grep ' "500 ' /var/log/nginx/access.log | \
  awk '{print $7}' | \
  sed 's/\?.*//' | \
  sort | uniq -c | sort -rn | head -10

The pipeline works as follows: grep filters for lines containing "500 (the HTTP status code with surrounding spaces to avoid matching 1500 or 5000). awk extracts the request path (column 7, the URL path). sed removes query strings by deleting everything after ?. sort groups identical paths together. uniq -c counts occurrences. sort -rn sorts by count descending. head -10 shows the top 10.

Mini Project: Server Health Dashboard Script

Write a Bash script that collects system health data and outputs a formatted status report. Include disk usage (df -h), memory usage (free -h), top CPU processes (ps aux --sort=-%cpu), listening ports (ss -tuln), and recent kernel messages (dmesg -H | tail -10).

#!/bin/bash
# Server health report
echo "=== Disk Usage ==="
df -h | grep -v tmpfs
echo ""
echo "=== Memory Usage ==="
free -h
echo ""
echo "=== Top 5 CPU Processes ==="
ps aux --sort=-%cpu | head -6
echo ""
echo "=== Listening Ports ==="
ss -tuln
echo ""
echo "=== Recent Kernel Messages ==="
dmesg -H | tail -10

This script can run via cron to email the report daily or on demand when troubleshooting. It replaces manually running each command separately and ensures you do not forget to check something critical.

What is the difference between SIGTERM and SIGKILL?

SIGTERM (signal 15) asks a Process to terminate gracefully, allowing it to clean up resources, close files, and flush buffers. SIGKILL (signal 9) immediately terminates the Process at the kernel level with no cleanup possible. Always use SIGTERM first. Only use SIGKILL when a Process ignores SIGTERM or is causing system instability.

How do I remember all these flags?

You do not need to memorize everything. Memorize the most common combinations (ls -lart, ps aux, curl -I, df -h) and use man command or command --help for specialty flags. Create aliases in your .bashrc or .zshrc. Over time, muscle memory builds for the flags you use daily.

Are these commands available on macOS?

Yes, with minor differences. macOS uses BSD-style commands while Linux uses GNU-style. Core functionality is identical for ls, cd, pwd, grep, kill, curl, ping, top. Differences: sed on macOS requires sed -i '' '' with empty backup string. awk behaves differently for some gawk-specific features. df shows different column widths. Install coreutils from Homebrew for GNU-compatible versions.

What is the difference between grep -E and grep without -E?

Without -E, grep uses basic regular expressions where +, ?, {, }, (, ), | must be escaped with backslash. With -E (extended), these metacharacters work without escaping. Most modern usage favors -E for readability. The -P flag enables Perl-compatible regular expressions (PCRE) with features like lookahead/lookbehind, but -P is not available on all systems.

Practice Questions

  1. Your web server is returning 502 Bad Gateway errors. List the commands you would use to diagnose whether the problem is network-level (host unreachable), port-level (nothing listening), or application-level (Process crashed).

  2. Write a one-liner that counts unique IP addresses in an Apache access log and outputs them sorted by frequency using only commands from this list.

  3. A disk volume is at 95 percent usage. Write the command sequence to identify the largest directories, identify old log files, and safely free space.

  4. A background Process consumes 99 percent CPU and is unresponsive to SIGTERM. What is the correct diagnostic and remediation sequence?

  5. Write a pipeline that extracts lines containing "ERROR" from a log file, replaces the timestamp format from ISO 8601 to Unix epoch, and outputs to a new file using sed only.

Brand Credit

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. These terminal commands are used daily in our engineering workflows — from debugging production incidents in Durga Antivirus Pro's scanning infrastructure to automating build and deployment pipelines for Doda Browser releases.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro