Linux

Linux Scenario Commands

Lesson 2 of 3 · 25 min · All Levels

Every command you need to navigate, troubleshoot, analyze logs, and manage production Linux servers—organized by the exact practical scenarios engineers face every day.

2. Working with Files

Files are what you spend most of your time with: creating them, reading them and checking what they are. touch creates an empty file, cat prints a small file, and less lets you scroll through a big one without flooding the screen. The file command is a quick way to find out if something is text, a script, an image or a compressed archive, since Linux does not depend on file extensions.

Scenario: Create files and put some text in them

# Creates empty files. If the file already exists it only updates the timestamp, so it is safe.
$ touch notes.txt todo.txt

# Creates a hidden file. Anything starting with a dot is hidden.
$ touch .hidden_config

# Writes text into a file. A single > overwrites what was there.
$ echo "Hello Linux" > notes.txt

# Adds a line at the end. Double >> appends instead of overwriting.
$ echo "Second line" >> notes.txt

Scenario: Read a file

# Prints the whole file. Good for short files.
$ cat notes.txt

# Same, with line numbers.
$ cat -n notes.txt

# Opens a big file page by page. Press q to quit, /word to search, space to go down.
$ less bigfile.log

# First 20 lines. Handy to check the header of a CSV.
$ head -n 20 app.log

# Last 50 lines. The newest entries in a log are at the bottom.
$ tail -n 50 app.log

# Follows the file live as new lines are written. Press Ctrl+C to stop.
$ tail -f app.log

Scenario: What kind of file is this?

# Tells you the real type: ASCII text, script, executable, gzip data and so on.
$ file notes.txt

# Confirms it is a shell script and not a binary.
$ file script.sh

# Full details: size, permissions, owner, and access, modify and change times.
$ stat notes.txt

# Counts lines. Use wc -w for words.
$ wc -l notes.txt

3. Creating and Removing Directories

Directories are folders. mkdir creates them and rmdir removes empty ones. The -p option is the one to remember: it creates every missing parent folder in one go, so you can build a whole tree with a single command. rmdir is deliberately strict and refuses to remove a folder that still has anything inside it.

Scenario: Build a practice directory tree

# Creates one directory.
$ mkdir practice

# Creates the parent and three sub-folders together. The {} braces expand into three names.
$ mkdir -p practice/{docs,images,backup}

# Same idea for dated folders.
$ mkdir -p logs/{2026-01,2026-02,2026-03}

# Draws the tree so you can verify it (install the tree package if missing).
$ tree practice

# Limits the drawing to two levels.
$ tree -L 2

# Shows the permissions of the directory itself, not its contents.
$ ls -ld practice

Scenario: mkdir says "cannot create directory ... No such file or directory"

# The parent folders a and b did not exist. -p creates all of them.
$ mkdir -p a/b/c

Scenario: rmdir says "Directory not empty"

# Works only when the folder is completely empty.
$ rmdir images

# Check what is inside, including hidden files that block rmdir.
$ ls -A images

# Removes the folder and everything inside. Think before pressing Enter.
$ rm -r images

4. Copy, Move, Rename and Delete

These four commands change your files, and Linux does not ask twice. cp copies, mv moves or renames (it is the same command, only the destination differs), and rm deletes permanently. There is no recycle bin. That is why the -i option, which asks before overwriting or deleting, is worth using while you are learning.

Scenario: Practice lab: create a tree, copy, rename and remove

# Start from the home directory.
$ cd ~

# Build the tree.
$ mkdir -p practice/{docs,images,backup}

# Move into docs using a relative path.
$ cd practice/docs

# Create two normal files and one hidden file.
$ touch notes.txt todo.txt .hidden_config

# Put some content in notes.txt.
$ echo "Hello Linux" > notes.txt

# Copy to another folder.
$ cp notes.txt ../backup/

# Copy inside the same folder under a new name.
$ cp notes.txt notes_copy.txt

# Rename. Same folder, new name.
$ mv todo.txt tasks.txt

# Move the file to the images folder.
$ mv tasks.txt ../images/

# Go back to the top of the tree.
$ cd ~/practice

# View the whole tree to confirm every step.
$ ls -R

# Delete a single file.
$ rm docs/notes_copy.txt

# Delete a folder with its contents.
$ rm -r backup

# Fails because images is not empty. Empty it first or use rm -r.
$ rmdir images

Scenario: Copy options that matter

# Copying a folder needs -r (recursive). Without it you see "omitting directory".
$ cp -r docs docs_backup

# Archive copy. Keeps permissions, owner and timestamps. Best for config backups.
$ cp -a /etc/nginx /etc/nginx.bak

# Asks before overwriting b.txt.
$ cp -i a.txt b.txt

# Never overwrites an existing file.
$ cp -n a.txt b.txt

# Prints each file as it is copied.
$ cp -v *.txt backup/

Scenario: Move and rename safely

# Asks before replacing a file that already exists.
$ mv -i old.txt new.txt

# Plain rename.
$ mv report.txt report_final.txt

# Renames many files at once from .txt to .bak.
$ for f in *.txt; do mv "$f" "${f%.txt}.bak"; done

Scenario: Delete without regrets

# Always list the pattern first and see exactly what will go.
$ ls *.tmp

# Then delete the same pattern.
$ rm *.tmp

# Asks for confirmation on each file.
$ rm -i file.txt

# Forces deletion without asking, also for write-protected files.
$ rm -f file.txt

# Quote names that contain spaces, or the shell treats them as two files.
$ rm "my file.txt"

# Deletes a file whose name starts with a dash. The -- tells rm that options have ended.
$ rm -- -report.txt

# Makes rm ask every time. Add it to ~/.bashrc to keep it.
$ alias rm='rm -i'

6. Log Analysis

Logs are the first place to look when something breaks. Most log work is the same four moves: watch the end of the file, count how often something happens, narrow it to a time window, and group the results to find the most common problem. Combining grep, awk, sort and uniq with pipes (|) gets you there without any special tool.

Scenario: The application is throwing errors. What and how often?

# Read the latest 100 lines first.
$ tail -n 100 app.log

# Watch the log live while you reproduce the problem.
$ tail -f /var/log/app.log

# Counts the number of error lines.
$ grep "ERROR" app.log | wc -l

# Only entries from 2 PM on that date.
$ grep "2026-11-02 14:" app.log

# Groups errors by one column and shows the most frequent first.
$ grep "ERROR" app.log | awk '{print $5}' | sort | uniq -c | sort -nr | head

# Searches rotated logs that are already compressed.
$ zgrep "ERROR" app.log.2.gz

# Prints only lines 10 to 20.
$ sed -n '10,20p' app.log

Scenario: Web server access logs

# Top 10 IP addresses hitting the server.
$ awk '{print $1}' access.log | sort | uniq -c | sort -nr | head

# Count of each HTTP status code.
$ awk '{print $9}' access.log | sort | uniq -c | sort -nr

# URLs that return 500 errors most often.
$ awk '$9 == 500 {print $7}' access.log | sort | uniq -c | sort -nr | head

Scenario: System logs

# Errors since the last boot.
$ journalctl -p err -b

# Everything logged in the last hour.
$ journalctl --since "1 hour ago"

# Recent kernel messages with readable time.
$ dmesg -T | tail -20

# Failed SSH logins on Ubuntu or Debian (use /var/log/secure on RHEL).
$ sudo grep "Failed password" /var/log/auth.log

7. Text Processing

Linux treats almost everything as text, and a handful of small tools can slice that text in useful ways. cut takes columns, sort orders lines, uniq removes or counts repeats, tr swaps characters, and awk and sed handle anything more complex. They are meant to be chained together, with the output of one passed to the next using a pipe.

Scenario: Pull fields out of a messy file

# Takes columns 1 and 3 from a comma-separated file.
$ cut -d',' -f1,3 users.csv

# Lists all usernames on the system.
$ cut -d: -f1 /etc/passwd

# Lists real users, skipping system accounts.
$ awk -F: '$3 >= 1000 {print $1}' /etc/passwd

# Adds up the second column.
$ awk '{sum+=$2} END {print sum}' sales.txt

# Joins two files side by side.
$ paste file1.txt file2.txt

Scenario: Sort, remove duplicates, count

# Sorts by column 2 as numbers.
$ sort -k2 -n data.txt

# Sorts and removes duplicate lines.
$ sort -u file.txt

# Shows only the lines that repeat.
$ sort file.txt | uniq -d

# Counts how many times each line appears.
$ sort file.txt | uniq -c

# Converts text to upper case.
$ tr 'a-z' 'A-Z' < file.txt

# Number of lines.
$ wc -l file.txt

Scenario: Compare and edit

# Shows what is different between two files.
$ diff dev.conf prod.conf

# Unified format, easier to read.
$ diff -u dev.conf prod.conf

# Replaces text in the file and keeps a .bak backup of the original.
$ sed -i.bak 's/8080/9090/g' app.conf

# Prints a range of lines without changing the file.
$ sed -n '10,20p' app.log

8. Disk Space

A full disk is one of the most common reasons an application stops working. The job is always the same: first find which filesystem is full (df), then find which folder is using the space (du), then clean up safely. Remember that a disk can also be "full" because it ran out of inodes, which are the entries that track files, even when free space is shown.

Scenario: The server is at 100% disk and the app cannot write

# Shows each filesystem with used and free space.
$ df -h

# Size of each folder under /var, smallest to largest.
$ du -sh /var/* | sort -h

# Ten biggest files or folders in the log directory.
$ du -ah /var/log | sort -rh | head -10

# Large files on the current filesystem, hiding permission errors.
$ find / -xdev -type f -size +500M 2>/dev/null

# Empties a log file without deleting it. Safe for a running application.
$ > bigfile.log

Scenario: Disk shows free space but files cannot be created

# Shows inode usage. 100% here means too many small files.
$ df -i

# Counts files in a suspect folder.
$ find /tmp -type f | wc -l

Scenario: I deleted a big file but the space did not come back

# Lists files that were deleted but are still held open by a process.
$ lsof +L1

# Same check using grep.
$ lsof | grep deleted

# Restarting the process releases the space.
$ systemctl restart myapp

9. Permissions and Ownership

Every file has an owner, a group and three sets of permissions: read (r), write (w) and execute (x) for the owner, the group and everyone else. In numbers, r is 4, w is 2 and x is 1, so 755 means the owner can do everything while others can read and execute, and 644 means the owner can read and write while others can only read. Most "Permission denied" messages are solved by checking ls -l and then fixing the owner or the mode.

Scenario: The deployment script says "Permission denied"

# Look at the permission string first.
$ ls -l deploy.sh

# Makes the script executable.
$ chmod +x deploy.sh

# Owner full access, others read and execute.
$ chmod 755 deploy.sh

# Normal file: owner writes, everyone reads.
$ chmod 644 notes.txt

# Owner read/write, group read, others nothing. Good for passwords.
$ chmod 640 secrets.conf

# Gives the owner write permission.
$ chmod u+w file

# Shows permissions in both letter and number form.
$ stat file.txt

Scenario: Change who owns a file

# Changes owner and group of a folder and everything in it.
$ chown appuser:appgroup /opt/app -R

# Changes only the group.
$ chgrp devs report.txt

# Shows the default permission mask applied to new files.
$ umask

Scenario: A developer cannot write to the shared folder

# Check the folder permissions.
$ ls -ld /shared

# See which groups the user belongs to.
$ id username

# Group write plus setgid, so new files inherit the folder's group.
$ chmod g+ws /shared

# Sticky bit. Users can delete only their own files, like /tmp.
$ chmod +t /shared

10. Processes and Performance

A process is a running program. When a server feels slow, you want to know three things: what is using the CPU, what is using memory, and whether the disk or network is the real bottleneck. top and ps answer the first two. vmstat and iostat help with the third. Signals such as kill send a request to a process, with the polite version first and the forced version only as a last resort.

Scenario: The server is slow

# Load average for the last 1, 5 and 15 minutes.
$ uptime

# Live view. Press M to sort by memory and P to sort by CPU, q to quit.
$ top

# A friendlier version of top, if installed.
$ htop

# Top memory-consuming processes.
$ ps aux --sort=-%mem | head

# Top CPU-consuming processes.
$ ps aux --sort=-%cpu | head

# Find a particular process and its PID.
$ ps -ef | grep java

# Memory and swap usage.
$ free -h

Scenario: Stop a process

# Sends SIGTERM, a polite request to shut down.
$ kill 1234

# Sends SIGKILL. Forced stop, with no cleanup. Use only if kill did not work.
$ kill -9 1234

# Kills processes by name.
$ pkill -f myapp

Scenario: Port 8080 is already in use

# Shows which process is listening on the port.
$ ss -tulnp | grep 8080

# Another way to see the same thing.
$ lsof -i :8080

# Stop the process holding the port.
$ kill <PID>

Scenario: Load is high but CPU looks fine

# Samples every 2 seconds, 5 times. Watch the wa (I/O wait) column.
$ vmstat 2 5

# Disk statistics. A high await value means a slow disk.
$ iostat -x 2

# Shows which process is hammering the disk.
$ iotop

# Checks if the kernel killed something for lack of memory.
$ dmesg | grep -i "out of memory"

Scenario: Run something at a lower priority or in the background

# Starts a job with lower priority.
$ nice -n 10 ./heavy_job.sh

# Runs in the background of the current terminal.
$ ./script.sh &

# Keeps running even if your SSH session drops.
$ nohup ./script.sh &

# Lists background jobs of this terminal.
$ jobs

11. Networking

When one system cannot talk to another, work from the bottom up: is the host reachable, is the name resolving, is the port open, and does the service answer? ping, nslookup or dig, nc and curl each test one of those layers. ip shows how your own machine is configured.

Scenario: The app cannot reach the database server

# Checks if the host answers at all.
$ ping -c 4 10.0.0.20

# Shows where the path stops (tracepath if traceroute is missing).
$ traceroute 10.0.0.20

# Tests if a specific port is open.
$ nc -zv 10.0.0.20 5432

# Checks that the name resolves.
$ nslookup db.company.com

# Quick DNS answer.
$ dig +short db.company.com

# Your IP addresses and network interfaces.
$ ip a

# Routing table and default gateway.
$ ip route

# Which DNS servers this machine uses.
$ cat /etc/resolv.conf

Scenario: Is the web service responding, and how fast?

# Headers only, including the status code.
$ curl -I https://example.com

# Prints just the status code and the response time.
$ curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com

# Verbose output showing the full request and response.
$ curl -v http://localhost:8080/health

# Sends a JSON POST request to test an API.
$ curl -X POST -H "Content-Type: application/json" -d '{"id":1}' http://localhost:8080/api

# Downloads a file and resumes if interrupted.
$ wget -c https://example.com/file.iso

Scenario: What is listening on this server?

# All listening TCP and UDP ports with the process name.
$ ss -tulnp

# Same view from lsof.
$ sudo lsof -i -P -n | grep LISTEN

12. Firewall

If a service is running but nobody can connect from outside, the firewall is a common cause. The tools differ by distribution: ufw is common on Ubuntu, firewalld (firewall-cmd) on RHEL and CentOS, and iptables sits underneath both. Always test from the client side with nc or curl after changing a rule.

Scenario: The service is up but users cannot connect

# Firewall status and rules on Ubuntu.
$ sudo ufw status verbose

# Opens port 8080.
$ sudo ufw allow 8080/tcp

# Current rules on RHEL, CentOS and Rocky.
$ sudo firewall-cmd --list-all

# Adds the port so it survives a reboot.
$ sudo firewall-cmd --add-port=8080/tcp --permanent

# Applies the permanent changes.
$ sudo firewall-cmd --reload

# Lists the low-level rules without resolving names.
$ sudo iptables -L -n

# From another machine, confirm the port is now reachable.
$ nc -zv server-ip 8080

13. Services with Systemd

Most modern Linux servers manage background services such as nginx, mysql or your own application through systemd, and systemctl is the command to control it. journalctl reads the logs that systemd collects for each service. The usual routine is: check the status, read the log, fix, then restart.

Scenario: Nginx is down after a reboot

# Current state and the last few log lines.
$ systemctl status nginx

# Start it now.
$ systemctl start nginx

# Start automatically on every boot.
$ systemctl enable nginx

# Stop and start again.
$ systemctl restart nginx

# Re-read the config without dropping connections.
$ systemctl reload nginx

# Tests the config for syntax errors before you reload.
$ nginx -t

Scenario: Find what failed and why

# All services that failed.
$ systemctl list-units --failed

# Last 50 log lines for that service.
$ journalctl -u nginx -n 50

# Only the last hour.
$ journalctl -u nginx --since "1 hour ago"

# Follow the log live.
$ journalctl -u nginx -f

# Needed after editing a unit file in /etc/systemd/system, otherwise the change is ignored.
$ systemctl daemon-reload

14. Users and Groups

User accounts decide who can log in and what they can touch. Groups make it easier to give the same access to many people. The important detail is usermod -aG: the -a means append. Without it, the user is removed from every other group and only placed in the one you named.

Scenario: A new developer joins the team

# Creates the user with a home folder, a shell and a group.
$ sudo useradd -m -s /bin/bash -G devs ravi

# Sets the password.
$ sudo passwd ravi

# Adds to one more group without removing the others.
$ sudo usermod -aG docker ravi

# Confirms the groups.
$ id ravi

# Shows password expiry details.
$ sudo chage -l ravi

Scenario: Someone is leaving or on long leave

# Locks the account.
$ sudo passwd -l ravi

# Deletes the user and the home directory.
$ sudo userdel -r ravi

Scenario: Who is logged in and who tried to?

# Users logged in now.
$ who

# Same, plus what each person is running.
$ w

# Last 10 logins.
$ last -n 10

# Failed login attempts.
$ sudo lastb

Scenario: Give limited admin rights

# Edit the sudoers file. It checks syntax so you do not lock yourself out.
$ sudo visudo

# Shows what commands that user may run with sudo.
$ sudo -l -U ravi

15. Scheduling Jobs

cron runs commands automatically at fixed times, and it is how backups, cleanups and reports are usually scheduled. A cron line has five time fields (minute, hour, day of month, month, day of week) followed by the command. at is for a job that should run only once.

Scenario: Run a backup every night at 2 AM

# Edit your cron jobs.
$ crontab -e

# List them.
$ crontab -l

# Every day at 2:00, with output saved to a log.
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1

# Every 15 minutes.
*/15 * * * * /opt/scripts/check.sh

# Weekdays at 9:00.
0 9 * * 1-5 /opt/scripts/report.sh

Scenario: The cron job does not run but works manually

# Find the full path to use inside the script. Cron has a very small PATH.
$ which python3

# Make sure the script is executable.
$ chmod +x /opt/scripts/backup.sh

# Cron activity on Debian and Ubuntu (RHEL uses /var/log/cron).
$ grep CRON /var/log/syslog

Scenario: One-time jobs

# Schedules a command for later. Type the command, then Ctrl+D.
$ at now + 10 minutes

# Lists pending at jobs.
$ atq

16. Shell, Environment and Redirection

The shell is the program that reads your commands. It keeps environment variables, such as PATH, and lets you control where input and output go. Many "works on my terminal but fails in cron or Jenkins" problems come from a different environment. Redirection and chaining operators let you build small command lines that do real work.

Scenario: Script works in my terminal but fails elsewhere

# Lists all environment variables.
$ env

# Where the shell looks for commands.
$ echo $PATH

# Sets a variable for this session and its child processes.
$ export APP_ENV=production

# Shows one variable.
$ printenv APP_ENV

# Reloads the settings after editing.
$ source ~/.bashrc

# Exit code of the last command. 0 means success.
$ echo $?

Scenario: Control the output

# Output to a file, overwriting it.
$ command > out.log

# Output added to the end of the file.
$ command >> out.log

# Output and errors both go to the same file.
$ command > out.log 2>&1

# Hide the error messages.
$ command 2>/dev/null

# Show on screen and save to a file at the same time.
$ command | tee out.log

Scenario: Chain commands

# Run cmd2 only if cmd1 worked.
$ cmd1 && cmd2

# Run cmd2 only if cmd1 failed.
$ cmd1 || cmd2

# Run both, no matter what.
$ cmd1 ; cmd2

# Creates a shortcut. Add to ~/.bashrc to keep it.
$ alias ll='ls -lah'

17. Package Management

Software is installed through the package manager of your distribution: apt on Debian and Ubuntu, yum or dnf on RHEL, CentOS and Rocky. It downloads the software with its dependencies and keeps track of what is installed, so you can also ask which package a file came from.

Scenario: Install a tool and check what is installed

# Refresh the package list, then install (Ubuntu and Debian).
$ sudo apt update && sudo apt install -y htop

# Check if a package is installed.
$ apt list --installed | grep nginx

# Installed version versus the available version.
$ apt-cache policy nginx

# Removes the package and keeps its config.
$ sudo apt remove nginx

# Removes the package and its config.
$ sudo apt purge nginx

# Install on RHEL-family systems (dnf works the same way).
$ sudo yum install -y htop

# List installed packages matching a name.
$ rpm -qa | grep nginx

# Which package owns this file.
$ rpm -qf /usr/sbin/nginx

# What was installed or removed, and when.
$ yum history

18. Storage, Disks and Mounts

A new disk is useless until it is partitioned, formatted and mounted. The steps are always the same: identify the disk, create a filesystem, mount it, and add it to /etc/fstab so it comes back after a reboot. Be careful, because formatting destroys everything on the disk.

Scenario: Attach a new disk and make it usable

# Lists disks and partitions, and where they are mounted.
$ lsblk

# Partition details.
$ sudo fdisk -l

# Formats the partition. This erases all data on it.
$ sudo mkfs.ext4 /dev/sdb1

# Create the mount point.
$ sudo mkdir /data

# Mount the disk.
$ sudo mount /dev/sdb1 /data

# Confirm it is mounted with the right size.
$ df -h /data

# Shows the UUID to use in /etc/fstab.
$ blkid /dev/sdb1

# Tests the fstab entries before you reboot.
$ sudo mount -a

19. Archive, Backup and File Transfer

Before you change anything on a production server, take a copy. tar bundles many files into one archive and can compress it. scp and rsync move files between machines over SSH, and rsync is the better choice for repeated copies because it sends only what changed.

Scenario: Back up before making changes

# Backup of a folder with today's date in the name.
$ cp -a /etc/nginx /etc/nginx.bak_$(date +%F)

# Creates a compressed archive.
$ tar -czvf backup_$(date +%F).tar.gz /opt/app

# Lists the contents without extracting.
$ tar -tzf backup.tar.gz

# Extracts into a chosen folder.
$ tar -xzvf backup.tar.gz -C /tmp/restore

# Zip format, useful for Windows users.
$ zip -r app.zip /opt/app

# Unzips into a given folder.
$ unzip app.zip -d /tmp/app

Scenario: Copy to another server

# Simple one-time copy over SSH.
$ scp backup.tar.gz user@10.0.0.5:/backup/

# Syncs a folder and transfers only the changes.
$ rsync -avz /opt/app/ user@10.0.0.5:/backup/app/

# Run on both machines and compare to confirm the file arrived intact.
$ sha256sum file.tar.gz

21. SSH and Security

SSH is how you log in to remote Linux servers. Key-based login is safer and faster than passwords: you keep a private key, the server holds the matching public key. SSH is also strict about permissions, and most login failures come down to wrong file permissions or the wrong user name.

Scenario: Set up passwordless login to a server

# Creates a key pair.
$ ssh-keygen -t ed25519

# Installs your public key on the server.
$ ssh-copy-id user@10.0.0.5

# Logs in without a password.
$ ssh user@10.0.0.5

# Uses a specific key file.
$ ssh -i ~/.ssh/mykey.pem user@10.0.0.5

# Local port forward, a tunnel to a service on the server.
$ ssh -L 8080:localhost:80 user@10.0.0.5

Scenario: SSH says "Permission denied (publickey)" or "UNPROTECTED PRIVATE KEY FILE"

# Private keys must be readable only by you.
$ chmod 600 ~/.ssh/id_ed25519

# The .ssh folder must be private as well.
$ chmod 700 ~/.ssh

# Same rule on the server side.
$ chmod 600 ~/.ssh/authorized_keys

# Very detailed debug output showing why the login failed.
$ ssh -vvv user@10.0.0.5

Scenario: Check for suspicious activity

# IPs with the most failed SSH logins.
$ sudo grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head

# Recent successful logins.
$ last -n 20

# Anything listening that should not be.
$ sudo ss -tulnp

22. System Information

Before you work on any server, find out what it is: which distribution, which kernel, how much memory and CPU, and how long it has been running. This is also the first thing to collect when you raise a support ticket or investigate an unexpected reboot.

Scenario: What kind of server is this?

# Distribution name and version.
$ cat /etc/os-release

# Kernel version.
$ uname -r

# Everything about the kernel and hostname in one line.
$ uname -a

# The server name. Check it before running risky commands.
$ hostname

# IP addresses of the server.
$ hostname -I

# CPU model and number of cores.
$ lscpu

# Just the number of CPU cores.
$ nproc

# Memory in readable units.
$ free -h

Scenario: How long has it been up, and did it reboot?

# Time since boot and load average.
$ uptime

# Exact time of the last boot.
$ uptime -s

# History of reboots.
$ last reboot

# Logs from the previous boot, to see why it went down.
$ journalctl -b -1

# Timezone and whether time sync is working.
$ timedatectl

# Current date and time on the server.
$ date

23. History, Help and Daily Habits

Nobody remembers every option. Linux has the manual built in, and the shell remembers what you typed. Learning how to look things up and how to repeat commands saves more time than memorising flags.

Scenario: Look things up

# Full manual for a command. Press q to leave.
$ man tar

# Short summary of the options.
$ tar --help

# Finds commands by description when you forgot the name.
$ apropos "copy files"

# Same search.
$ man -k copy

Scenario: Reuse what you typed

# List of previous commands.
$ history

# Only the last 20.
$ history 20

# Find an old command.
$ history | grep tar

# Repeat the last command.
$ !!

# Repeat the last command with sudo, when you forgot it.
$ sudo !!

# Search your history while typing.
Ctrl+R

# Autocompletes file names and avoids typing mistakes.
Tab

Scenario: Long tasks and repeated checks

# Re-runs a command every 2 seconds.
$ watch -n 2 df -h

# A terminal session that keeps running even when SSH disconnects.
$ tmux

# Creates a 1 GB test file quickly.
$ fallocate -l 1G test.img

# Clears the screen. Ctrl+L does the same.
$ clear

Scenario: Habits that prevent mistakes

# Run before any delete, move or recursive change.
$ pwd

# See the list before you delete it.
$ ls pattern, then rm pattern

# Back up a file before editing it.
$ cp -a file file.bak

# Confirm which server you are on before running anything serious.
$ hostname