The advanced Linux Cheat Sheet
TLDR; The Advanced Linux Cheat Sheet covers SSH, package managers, processes and shell jobs, systemd services and logs, text processing, pipes and redirection, system inspection, networking, archives, environment variables and shell history. Each section includes example command output and explains the files it reads or creates. The examples use Bash and GNU tools on Linux; service and package commands name their required system or distribution family.
Download The Advanced Linux Cheat Sheet
Get The Advanced Linux Cheat Sheet as a and by email.

Request the complete printable PDF and full-resolution PNG. We will send both files directly to your inbox.
What Should You Know Before Starting?
The Advanced Linux Cheat Sheet continues the Ultimate Linux Basics Cheat Sheet. Read that beginner guide first if you need an introduction to terminals, shells, files, text search, permissions or sudo.
How Should You Read The Examples?
Lines beginning with $ are commands. Lines beginning with ### show example output, and # No output on success marks commands that normally finish silently. Do not type these prefixes or output lines. [excerpt] means that some output has been omitted. Output is illustrative: process IDs, addresses, dates, sizes, versions and package messages vary by machine.
Use a scratch directory for the sample files below. Each file-content block shows exactly what to save under the named filename, including a newline after the last line. System files such as /etc/passwd are read-only examples here; inspect your existing files instead of replacing them. Sections can be read independently; where a command changes a sample file, the result is shown.
What Do The Input Files Look Like?
In this blog post, we assume the files used in the examples have the following contents. Create these sample files in a scratch directory if you want to follow along. The /etc/passwd excerpt is an example of an existing system file; do not replace it.
access.log is a simplified request log with one request per line. Real web-server logs usually include timestamps and other fields.
GET /health 200
GET /api 200
GET /health 200
GET /api 500
GET /health 200
application.log contains three short messages.
INFO server started
WARN disk almost-full
INFO request complete
settings.old is the previous configuration:
environment=development
port=8080
settings.new is the replacement configuration:
environment=production
port=8080
settings.conf starts with the same content as settings.old. The sed example displays a replacement without changing this file.
data.txt has three whitespace-separated columns: service, replica count and environment. It has no header row.
api 3 production
worker 2 staging
web 1 development
/etc/passwd is a system account file. Each colon-separated record contains a login name, password placeholder, user ID, group ID, comment, home directory and login shell. A shortened example looks like this:
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
ada:x:1000:1000:Ada:/home/ada:/bin/bash
How Do You Use SSH?
ssh, short for Secure Shell, opens an encrypted shell on another machine. In username@host, replace username with the account you want to use on the remote machine, such as deploy, and replace host with that machine's hostname or IP address. Avoid direct root login: use an ordinary account and run individual administrative commands with sudo when needed. Many SSH servers disable root login by default.
# open an encrypted remote shell
$ ssh deploy@example.com
## => output
### [example after successful authentication]
### Last login: Mon Aug 10 09:00:00 2026 from 192.0.2.10
### deploy@server:~$
# connect using an IP address
$ ssh deploy@192.0.2.25
## => output
### [example after successful authentication]
### deploy@server:~$
# connect on a non-default port (OpenSSH provides only the short -p form)
$ ssh -p 2222 deploy@example.com
## => output
### [example after successful authentication on port 2222]
### deploy@server:~$
Run exit to close the SSH session and return to your local shell.
SSH displays a host-key fingerprint on the first connection. Verify it through a trusted channel before accepting it. A changed key can be legitimate after a reinstall, but it can also indicate that you are connecting to the wrong machine.
The authenticity of host '192.0.2.25 (192.0.2.25)' can't be established.
ED25519 key fingerprint is SHA256:<fingerprint>.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.0.2.25' (ED25519) to the list of known hosts.
<fingerprint> represents the server's actual fingerprint. Compare it with the value supplied by the server administrator before entering yes.
How Do You Install Packages Across Linux Distributions?
Use the package manager belonging to your distribution. Package names sometimes differ, and mixing package managers can damage the system's understanding of installed software.
To follow the service examples later in this article, use only the subsection for your distribution and install the at package. It provides the atd daemon, which runs commands queued for later execution without opening a network port. Do not run the removal command until you have finished the tutorial. The output below is illustrative: review the complete package list, disk-space changes and confirmation prompt before approving a transaction. These commands read distribution-managed repository metadata and package databases, so no sample input file is required.
The at package schedules commands to run once at a later time. The at command adds jobs to the queue, atq displays queued jobs, atrm removes them and the atd background daemon executes them. Use cron instead when a job must repeat on a schedule.
How Do You Use apt On Debian And Ubuntu?
apt, short for Advanced Package Tool, installs, removes, updates and inspects packages on Debian-based systems.
# refresh available package metadata
$ sudo apt update
## => output
### [excerpt]
### Reading package lists... Done
### Building dependency tree... Done
### Reading state information... Done
### All packages are up to date.
# install at for the examples later in this article
$ sudo apt install at
## => output
### [excerpt before the confirmation prompt]
### The following NEW packages will be installed:
### at
### [dependency list and download sizes omitted]
# remove at after the tutorial only if you no longer need it
$ sudo apt remove at
## => output
### [excerpt before the confirmation prompt]
### The following packages will be REMOVED:
### at
### [transaction details omitted]
# install available upgrades
$ sudo apt upgrade
## => output
### [example when no upgrades are available]
### Reading package lists... Done
### Building dependency tree... Done
### Reading state information... Done
### Calculating upgrade... Done
### 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
# search and inspect packages
$ apt search at
## => output
### [excerpt; version and repository omitted]
### at/...
### delayed job execution and batch processing
$ apt show at
## => output
### [excerpt]
### Package: at
### Section: admin
### Description: delayed job execution and batch processing
How Do You Use dnf On Fedora And Red Hat Systems?
dnf, originally short for Dandified YUM, manages packages on Fedora and newer Red Hat-based systems.
# install at for the examples later in this article
$ sudo dnf install at
## => output
### [excerpt before confirmation; wording differs between DNF versions]
### Installing:
### at
### [dependencies and versions omitted]
### Transaction Summary
### [package counts and download sizes omitted]
# remove at after the tutorial only if you no longer need it
$ sudo dnf remove at
## => output
### [excerpt before confirmation]
### Removing:
### at
### [dependency and transaction details omitted]
$ sudo dnf upgrade
## => output
### [example when no upgrades are available]
### Nothing to do.
# search and inspect packages
$ dnf search at
## => output
### [excerpt]
### at.x86_64 : Job spooling tools
$ dnf info at
## => output
### [excerpt]
### Name : at
### Architecture : x86_64
### Summary : Job spooling tools
How Do You Use pacman On Arch Linux?
pacman, a shortened form of package manager, installs, removes, upgrades and queries packages on Arch Linux.
# synchronize repositories, upgrade the system and install a package (short: -Syu)
$ sudo pacman --sync --refresh --sysupgrade at
## => output
### [excerpt before confirmation]
### :: Synchronizing package databases...
### core
### extra
### :: Starting full system upgrade...
### resolving dependencies...
### looking for conflicting packages...
### [package versions and transaction details omitted]
# remove at after the tutorial only if you no longer need it (short: -R)
$ sudo pacman --remove at
## => output
### [excerpt before confirmation]
### checking dependencies...
### [package version and removal size omitted]
### :: Do you want to remove these packages? [Y/n]
# search repositories and inspect a package (--search short: -s; --info short: -i)
$ pacman --sync --search at
## => output
### [excerpt; version omitted]
### extra/at ...
### AT and batch delayed command scheduling utility and daemon
$ pacman --sync --info at
## => output
### [excerpt]
### Repository : extra
### Name : at
### Description : AT and batch delayed command scheduling utility and daemon
Arch Linux expects full system upgrades. Avoid refreshing package databases with pacman --sync --refresh and then installing a package without upgrading the rest of the system.
How Do You Start atd For The Following Examples?
After installing the at package, start its atd service now and enable it for future boots. This command requires a distribution that uses systemd:
# start atd now and after future boots
$ sudo systemctl enable --now atd
## => output
### [example when the enablement link does not already exist]
### Created symlink /etc/systemd/system/multi-user.target.wants/atd.service → /usr/lib/systemd/system/atd.service.
# confirm that atd is running
$ systemctl is-active atd
## => output
### active
Keep the at package installed and atd running while following the remaining examples. The process, service and log commands below can then show real atd output on your machine.
How Do You Manage Processes And Shell Jobs?
A process is a running program identified by a process ID, or PID. A shell job is a process or pipeline started from your current shell.
The new process and job commands are:
top: displays an interactive, continuously updated process list.pgrep: process grep — finds process IDs by name or other attributes.jobs: lists jobs started from the current shell.fg: foreground — resumes a shell job in the foreground.bg: background — resumes a stopped shell job in the background.
sleep 300 is a real, quiet command that waits for 300 seconds. Run the job-control examples in the same interactive Bash shell, before the timer finishes. They assume this is your first job, so its job number is 1.
# list processes for all users
$ ps aux
## => output
### [excerpt]
### USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
### daemon 1234 0.0 0.1 6900 1400 ? Ss 09:00 0:00 /usr/sbin/atd -f
# show a live, interactive process view
$ top
## => output
### [interactive screen excerpt; press q to quit]
### Tasks: 112 total, 1 running, 111 sleeping, 0 stopped, 0 zombie
### %Cpu(s): 2.0 us, 1.0 sy, 0.0 ni, 97.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
### PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
### 1234 daemon 20 0 6900 1400 1200 S 0.0 0.1 0:00.02 atd
# find processes by name and include their command lines (short: -a)
# Example output requires atd to be installed and running.
$ pgrep --list-full atd
## => output
### 1234 /usr/sbin/atd -f
# start a command in the background
$ sleep 300 &
## => output
### [1] 2468
# list jobs belonging to the current shell
$ jobs
## => output
### [1]+ Running sleep 300 &
# bring job 1 to the foreground
$ fg %1
## => output
### sleep 300
### [the shell waits; press Ctrl+Z before continuing]
### ^Z
### [1]+ Stopped sleep 300
# press Ctrl+Z while sleep is in the foreground, then resume it
$ bg %1
## => output
### [1]+ sleep 300 &
The Bash job-control manual describes jobs, fg and bg. Press Ctrl+Z to suspend the current foreground job. This does not terminate it; use fg or bg to resume it. Press Ctrl+C to send SIGINT to the foreground job and normally stop it completely; a program can handle or ignore that signal.
The BSD-style selection flags in ps aux do not have an exact set of long-option equivalents, so the familiar short form is retained here.
How Do You Stop A Process?
kill sends a signal to a process identified by its PID, or process ID. Start this harmless sleep process and then stop the same process:
# start a process that waits for five minutes
$ sleep 300 &
## => output
### [1] 2468
# replace 2468 with the PID printed when you ran sleep 300 above
# then request a graceful termination
$ kill -TERM 2468
# No output on success.
# stop every process named atd; run only when atd is installed and running
$ sudo pkill --exact atd
# No output on success.
# start atd again before continuing with the tutorial
$ sudo systemctl start atd
# No output on success.
In the example output, 2468 is the PID and [1] is the shell's job number. Your shell will print different numbers, so use the PID it prints instead of typing 2468. Earlier examples used 1234 as a placeholder PID; it did not refer to a real process on your computer. pkill sends a signal to every process whose name matches the pattern, so check the matching processes with pgrep --list-full atd before using it. Starting atd again keeps it available for the following service and log examples. SIGTERM gives a program a chance to close files and release resources. If a process cannot stop cleanly, kill -KILL <PID> is a last resort; SIGKILL cannot be handled or ignored. Confirm the PID immediately before sending a signal because PIDs can be reused.
The shell's kill command accepts signal names such as -TERM and -KILL, but it does not provide portable long forms for them.
How Do You Manage Services And Logs?
Most current mainstream distributions use systemd to start and supervise services. Minimal distributions and containers may use another init system, so first check whether systemctl exists.
atd below names the deferred-execution service installed by the at package; systemd resolves it as atd.service. The commands read its unit and current service state. Run lifecycle commands only on a service you intend to change.
# inspect a service and its recent messages
$ systemctl status atd
## => output
### [excerpt; press q if a pager opens]
### ● atd.service - Deferred execution scheduler
### Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; preset: enabled)
### Active: active (running) since Mon 2026-08-10 09:00:00 UTC; 1h ago
### Main PID: 1234 (atd)
### Tasks: 1
# start, stop or restart a service; normally requires root
$ sudo systemctl start atd
# No output on success.
$ sudo systemctl stop atd
# No output on success.
$ sudo systemctl restart atd
# No output on success.
# start now and automatically after future boots
$ sudo systemctl enable --now atd
## => output
### [example when the enablement symlink does not yet exist]
### Created symlink /etc/systemd/system/multi-user.target.wants/atd.service → /usr/lib/systemd/system/atd.service.
# prevent automatic startup without stopping the current process
$ sudo systemctl disable atd
## => output
### Removed "/etc/systemd/system/multi-user.target.wants/atd.service".
How Do You Read systemd Logs?
journalctl, short for journal control, reads and filters logs stored by the systemd journal.
# show the newest 100 messages for one service (short: -u and -n)
$ journalctl --unit atd --lines 100
## => output
### [excerpt; fewer than 100 lines if fewer entries exist]
### Aug 10 09:00:00 linux-demo systemd[1]: Starting atd.service - Deferred execution scheduler...
### Aug 10 09:00:00 linux-demo systemd[1]: Started atd.service - Deferred execution scheduler.
# follow new service messages; press Ctrl+C to stop (--follow short: -f)
$ journalctl --unit atd --follow
## => output
### [excerpt; remains open waiting for new entries]
### Aug 10 09:15:00 linux-demo systemd[1]: Started atd.service - Deferred execution scheduler.
# show errors from the current boot; press q if a pager opens (short: -p and -b)
$ journalctl --priority err --boot
## => output
### [example on a boot with no accessible error entries]
### -- No entries --
# show messages since a time; press q if a pager opens (short: -S)
$ journalctl --since '30 minutes ago'
## => output
### [excerpt]
### Aug 10 09:45:00 linux-demo systemd[1]: Started Daily apt download activities.
journalctl reads structured journal entries; atd does not require a local file called atd.log. Each displayed line includes a timestamp, hostname, source and message. The --follow example stays open for new entries; press Ctrl+C to stop following.
Some distributions also keep traditional text logs below /var/log. Access may require membership in an administrative group or sudo.
How Do You Sort, Count And Compare Data?
This section combines several text-processing commands:
sort: orders lines of text.|(pipe): passes the standard output of the command on its left to the standard input of the command on its right. Here, it sends the sorted lines fromsorttouniqfor counting.uniq: unique — filters or counts adjacent duplicate lines.cut: selects fields or character ranges from each line.wc: word count — counts lines, words and bytes.diff: difference — compares files line by line.sed: stream editor — transforms text using editing expressions.awk: named after Alfred Aho, Peter Weinberger and Brian Kernighan — processes structured text by fields and patterns.
What Do The Commands Print?
# Blank lines are also counted; see the explanation below if you see an extra `1`.
# sort lines, then count adjacent duplicates (short: -c)
$ sort access.log | uniq --count
## => output
### 1 GET /api 200
### 1 GET /api 500
### 3 GET /health 200
# print the first colon-separated field (short: -d and -f)
$ cut --delimiter=: --fields=1 /etc/passwd
## => output
### [excerpt matching the sample records above]
### root
### www-data
### ada
# count lines, words and bytes
$ wc application.log
## => output
### 3 9 64 application.log
$ wc --lines application.log # short: -l
## => output
### 3 application.log
# compare two files with a unified diff (short: -u)
$ diff --unified --label settings.old --label settings.new settings.old settings.new
## => output
### --- settings.old
### +++ settings.new
### @@ -1,2 +1,2 @@
### -environment=development
### +environment=production
### port=8080
# replace text in the displayed output; the file remains unchanged
$ sed 's/development/production/g' settings.conf
## => output
### environment=production
### port=8080
# print the first and third whitespace-separated fields
$ awk '{ print $1, $3 }' data.txt
## => output
### api production
### worker staging
### web development
uniq counts adjacent matches, so sorting first groups repeated requests. The wc columns are lines, words and bytes; see the GNU wc reference. The diff labels omit machine-specific timestamps: - marks a removed line and + marks an added line. diff returns exit status 1 when files differ; that is an expected comparison result.
Why Does uniq --count Sometimes Print A Blank Entry?
If access.log contains a blank line, sort keeps it and uniq --count treats it as one distinct line. The result starts with 1 followed by no text:
1
1 GET /api 200
1 GET /api 500
3 GET /health 200
Use cat -A access.log to make invisible characters visible. A blank line appears as a line containing only $. To create a cleaned copy without blank lines, use sed '/^$/d' access.log > access-without-blank-lines.log. The original access.log remains unchanged; access-without-blank-lines.log contains only the request records.
How Do Pipes And Redirection Work?
Every command starts with three standard streams: standard input, standard output and standard error. A pipe, |, sends one command's standard output into the next command's standard input.
The examples use these commands:
ps: process status — lists running processes. The process-management section below covers it in more detail.wc: word count — counts lines, words or bytes.printf: formats and writes text to standard output. It is a shell built-in in Bash and other common shells.ip: Internet Protocol — displays or changes network addresses, routes and interfaces.tee: copies standard input to both standard output and one or more files, like a T-shaped pipe.
# count all running processes (ps provides only the short -e form)
$ ps -e | wc --lines
## => output
### [example; your process count will differ]
### 112
# replace a file with standard output
$ printf 'production=true\n' > settings.conf
# No output on success.
# append instead of replacing
$ printf 'port=8080\n' >> settings.conf
# No output on success.
# display output and save a copy
$ ip -brief address | tee network-info.log
## => output
### lo UNKNOWN 127.0.0.1/8 ::1/128
### eth0 UP 192.0.2.10/24
The first pipeline reads the live process list; it does not read access.log or any other sample file in this article. ps -e lists all running processes and wc --lines counts the listing lines, including its header. The number changes as processes start and stop, so your output will differ from the example. ps and wc are standard tools on mainstream Linux distributions.
The first redirect replaces the earlier settings.conf. After both printf commands, its complete contents are:
production=true
port=8080
network-info.log contains the same address listing that tee displays. This .log file is plain text.
Be careful with >: the shell truncates the destination before the command runs. Use >> to append. When a root-owned file must be changed, sudo command > file may still fail because your current shell performs the redirection. One safe pattern is command | sudo tee file after you have verified the content and target.
How Do You Inspect A Linux System?
When troubleshooting, establish what system you are on before changing it.
These commands identify the system and its current resource state:
uname: Unix name — displays kernel and machine information.uptime: shows how long the system has run and its load averages.free: reports used and available memory and swap.lscpu: list CPUs — displays processor architecture information.nproc: number of processors — prints the available processing-unit count.hostnamectl: hostname control — displays or changes the system hostname and related metadata.
# kernel, architecture and hostname information (short: -a)
$ uname --all
## => output
### Linux linux-demo 6.8.0-60-generic #63-Ubuntu SMP PREEMPT_DYNAMIC Fri Apr 18 19:00:50 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
# distribution name and version
$ cat /etc/os-release
## => output
### [excerpt]
### PRETTY_NAME="Ubuntu 24.04.2 LTS"
### NAME="Ubuntu"
### VERSION_ID="24.04"
### ID=ubuntu
### ID_LIKE=debian
# current time, uptime and load averages
$ uptime
## => output
### 10:00:00 up 1 day, 2:15, 1 user, load average: 0.12, 0.08, 0.05
# readable memory and swap usage (short: -h)
$ free --human
## => output
### total used free shared buff/cache available
### Mem: 7.7Gi 1.8Gi 4.6Gi 32Mi 1.3Gi 5.6Gi
### Swap: 2.0Gi 0B 2.0Gi
# CPU information and available processing units
$ lscpu
## => output
### [excerpt]
### Architecture: x86_64
### CPU(s): 4
### On-line CPU(s) list: 0-3
### Thread(s) per core: 2
### Core(s) per socket: 2
### Socket(s): 1
$ nproc
## => output
### 4
# current hostname
$ hostnamectl
## => output
### [excerpt]
### Static hostname: linux-demo
### Operating System: Ubuntu 24.04.2 LTS
### Kernel: Linux 6.8.0-60-generic
### Architecture: x86-64
/etc/os-release is a text file with KEY=value entries identifying the distribution. The cat output above is an excerpt of that file. Commands such as free and lscpu read system information; you do not need to create input files for them.
Load average is not CPU percentage. It counts tasks running or waiting for resources over roughly 1, 5 and 15 minutes. Interpret it relative to the number of CPU cores and together with memory, I/O and process information.
How Do You Inspect Disks And Directories?
The storage commands are:
df: disk free — reports used and available filesystem space.du: disk usage — totals the space consumed by files and directories.lsblk: list block devices — displays disks, partitions and their attributes.mount: displays mounted filesystems or attaches a filesystem to the directory tree.
# filesystem capacity and free space (short: -h)
$ df --human-readable
## => output
### [excerpt]
### Filesystem Size Used Avail Use% Mounted on
### /dev/vda1 40G 12G 26G 32% /
### tmpfs 3.9G 0 3.9G 0% /dev/shm
# total size of one directory (short: -sh)
$ du --summarize --human-readable /var/log
## => output
### 128M /var/log
# compare immediate children by size (sort short: -h)
$ du --summarize --human-readable /var/* 2>/dev/null | sort --human-numeric-sort
## => output
### [excerpt; unreadable entries may be missing or undercounted]
### 4.0K /var/local
### 16M /var/tmp
### 128M /var/log
### 256M /var/cache
### 1.2G /var/lib
# inspect block devices, filesystem types and mount points (short: -f)
$ lsblk --fs
## => output
### [excerpt]
### NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
### vda
### └─vda1 ext4 1.0 2c631a21-0ba8-4d53-8cda-8beab0d63f42 26G 30% /
# list mounted filesystems
$ mount
## => output
### [excerpt]
### /dev/vda1 on / type ext4 (rw,relatime)
### proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
### tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
/var/log is a directory of logs, often containing files such as syslog and subdirectories such as journal/, depending on your distribution. /var/* selects the immediate non-hidden entries under /var. /dev/vda1 in the sample output is a disk partition, not a text file.
The totals from df and du can disagree when a running process still holds a deleted file open, when files are hidden below a mount point, or because of filesystem accounting.
Mounting, unmounting, partitioning and formatting storage are administrative operations. The related commands are:
umount: unmount — detaches a mounted filesystem; its name omits the first "n" for historical reasons.findmnt: find mount — searches and displays mounted filesystems.dd: copies and optionally converts raw data, including complete block devices.mkfs: make filesystem — creates a filesystem on a device; a type-specific command such asmkfs.ext4creates that particular filesystem.
Verify device names with lsblk --fs before using any of these commands.
How Do You Troubleshoot Linux Networking?
Start at the local machine, then test routing, name resolution, the remote host and finally the application port.
The networking commands introduced here are:
ping: sends ICMP echo requests to test reachability and measure response time.dig: domain information groper — queries the Domain Name System (DNS).ss: socket statistics — displays network socket information.curl: client for URLs — transfers data using protocols such as HTTP and HTTPS.traceroute: traces the network hops toward a destination.
# show a compact list of network addresses (short: -br)
$ ip -brief address
## => output
### lo UNKNOWN 127.0.0.1/8 ::1/128
### eth0 UP 192.0.2.10/24
# show routes, including the default gateway
$ ip route
## => output
### default via 192.0.2.1 dev eth0
### 192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.10
# send four reachability probes (ping provides only the short -c form)
$ ping -c 4 1.1.1.1
## => output
### PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
### 64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=12.1 ms
### 64 bytes from 1.1.1.1: icmp_seq=2 ttl=57 time=12.3 ms
### 64 bytes from 1.1.1.1: icmp_seq=3 ttl=57 time=12.0 ms
### 64 bytes from 1.1.1.1: icmp_seq=4 ttl=57 time=12.4 ms
###
### --- 1.1.1.1 ping statistics ---
### 4 packets transmitted, 4 received, 0% packet loss, time 3003ms
### rtt min/avg/max/mdev = 12.000/12.200/12.400/0.158 ms
# resolve a hostname when the dig utility is installed
$ dig example.com
## => output
### [illustrative answer-section excerpt; addresses change]
### ;; ANSWER SECTION:
### example.com. 300 IN A 93.184.215.14
# inspect listening TCP and UDP sockets with owning processes (short: -tulpn)
$ sudo ss --tcp --udp --listening --processes --numeric
## => output
### [excerpt]
### Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
### tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=900,fd=3))
# request HTTP response headers (short: -I)
$ curl --head https://example.com
## => output
### [header excerpt; progress meter omitted]
### HTTP/2 200
### content-type: text/html
### server: cloudflare
# show the path packets take when traceroute is installed
$ traceroute example.com
## => output
### [illustrative excerpt; * means no reply before the timeout]
### traceroute to example.com (93.184.215.14), 30 hops max, 60 byte packets
### 1 192.0.2.1 (192.0.2.1) 0.421 ms 0.389 ms 0.402 ms
### 2 * * *
A failed ping does not always mean a host is down; networks often block ICMP. Test the actual application protocol with a tool such as curl or ssh as well.
How Do You Copy Files Between Local And Remote Machines?
Two commands copy files through an SSH connection:
scp: secure copy — use it for a simple, one-time copy of a file or small directory over SSH.rsync: remote sync — use it for large directories or repeated transfers. It compares the source and destination, then transfers only new or changed data. Its--partialoption can also keep an interrupted partial transfer so a later run can continue it.
Replace deploy@example.com with your own SSH account and server. The examples assume the remote /tmp/ directory is writable. Run these commands from your local shell. The local report.txt contains:
Daily report
Requests: 1200
Errors: 3
The reports/ directory contains a copy named daily.txt with the same content:
reports/
└── daily.txt
# copy a local file to the remote machine
$ scp report.txt deploy@example.com:/tmp/
## => output
### report.txt 100% 38 3.8KB/s 00:00
# copy the remote file back into the current local directory
$ scp deploy@example.com:/tmp/report.txt ./report-from-server.txt
## => output
### report.txt 100% 38 3.8KB/s 00:00
# copy a local directory to the remote machine (short: -r)
$ scp -r reports deploy@example.com:/tmp/
## => output
### daily.txt 100% 38 3.8KB/s 00:00
# synchronize a local directory to the remote machine (short: -av)
$ rsync --archive --verbose --progress reports/ deploy@example.com:/tmp/reports/
## => output
### [excerpt for a transfer to an empty destination]
### sending incremental file list
### ./
### daily.txt
### 38 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=0/2)
# synchronize the remote directory back to a local directory
$ rsync --archive --verbose --progress deploy@example.com:/tmp/reports/ ./reports-from-server/
## => output
### [excerpt]
### receiving incremental file list
### ./
### daily.txt
In scp, the side containing deploy@example.com: is remote and the side without it is local. Reversing the source and destination reverses the copy direction. For rsync, the trailing slash in reports/ means “copy this directory's contents.” The transferred daily.txt keeps the contents shown above. Transfer progress and totals depend on file sizes and connection speed.
How Do You Download A File?
wget, short for web get, downloads files from web and FTP servers; curl was introduced in the networking section.
The URLs below are placeholders for endpoints on a server you control; example.com/status and example.com/archive.tar.gz are not promised download endpoints. Assume /status returns this JSON body and /archive.tar.gz serves a gzip-compressed tar archive containing the project/ tree shown in the next section.
{"status":"ok"}
# print a response body to the terminal
$ curl https://example.com/status
## => output
### [assumed response body; progress meter omitted]
### {"status":"ok"}
# follow redirects and preserve the remote filename (short: -LO)
$ curl --location --remote-name https://example.com/archive.tar.gz
## => output
### [illustrative progress meter]
### % Total % Received % Xferd Average Speed Time Time Time Current
### Dload Upload Total Spent Left Speed
### 100 220 100 220 0 0 2200 0 --:--:-- --:--:-- --:--:-- 2200
# download with wget when installed
$ wget https://example.com/archive.tar.gz
## => output
### [excerpt; assumes the local filename does not exist yet]
### HTTP request sent, awaiting response... 200 OK
### Length: 220 [application/gzip]
### Saving to: ‘archive.tar.gz’
### archive.tar.gz 100%[===================>] 220 --.-KB/s in 0s
### 2026-08-10 10:00:00 (2.10 MB/s) - ‘archive.tar.gz’ saved [220/220]
curl --remote-name saves the binary archive as archive.tar.gz; it does not print its contents as text. The wget example is an alternative download method. If that filename already exists, wget normally chooses a suffixed name such as archive.tar.gz.1.
Do not pipe an unknown internet response directly into a shell. Download it, inspect it, verify its source and checksum, and only then execute it if appropriate.
How Do You Create And Extract Archives?
An archive combines multiple files; compression makes the result smaller. This section introduces three archive commands:
tar: tape archive — creates, lists and extracts archives, optionally with compression.zip: creates or updates ZIP archives.unzip: lists or extracts ZIP archives.
The local project/ input directory contains two plain-text files:
project/
├── README.txt
└── settings.conf
project/README.txt contains:
Demo application
project/settings.conf contains:
environment=production
port=8080
project.tar.gz and project.zip are binary archives of this tree. Listing an archive shows member names; extracting it restores the directory and those file contents. Creation and extraction below are separate examples: for extraction, work in a fresh directory containing only a copy of the archive. The /tmp/project alternative assumes you have created an empty destination directory. Because the archive contains project/, that alternative produces /tmp/project/project/README.txt and /tmp/project/project/settings.conf.
# create a gzip-compressed tar archive (short: -c, -z and -f)
$ tar --create --gzip --file project.tar.gz project/
# No output on success.
# list its contents without extracting (--list short: -t)
$ tar --list --gzip --file project.tar.gz
## => output
### project/
### project/README.txt
### project/settings.conf
# extract into the current directory (--extract short: -x)
$ tar --extract --gzip --file project.tar.gz
# No output on success.
# extract into an existing destination directory (--directory short: -C)
$ tar --extract --gzip --file project.tar.gz --directory /tmp/project
# No output on success.
# create and extract zip archives when zip/unzip are installed (zip short: -r)
$ zip --recurse-paths project.zip project/
## => output
### adding: project/ (stored 0%)
### adding: project/README.txt (stored 0%)
### adding: project/settings.conf (stored 0%)
$ unzip project.zip
## => output
### Archive: project.zip
### creating: project/
### extracting: project/README.txt
### extracting: project/settings.conf
tar creation and extraction are normally silent without --verbose; listing prints the stored paths. The GNU tar manual documents these operations. The ZIP commands are an alternative: extract into an empty directory to avoid overwrite prompts.
Inspect an archive's file list before extracting content from an untrusted source. Extract it into a new empty directory so unexpected names cannot overwrite unrelated files.
How Do Environment Variables And Shell History Work?
Shell variables hold text for the current shell. Exported environment variables are inherited by programs started from that shell.
The shell built-ins and commands introduced here are:
export: marks a shell variable for inheritance by child processes.env: environment — displays the environment or runs a command with modified variables.unset: removes a shell variable or function.history: displays commands previously entered in the current shell.
# create and export a variable for child processes
$ export APP_ENV='production'
# No output on success.
# print one variable safely
$ printf '%s\n' "$APP_ENV"
## => output
### production
# list the environment
$ env
## => output
### [excerpt]
### HOME=/home/ada
### USER=ada
### SHELL=/bin/bash
### PATH=/usr/local/bin:/usr/bin:/bin
### APP_ENV=production
# remove a variable from the current shell
$ unset APP_ENV
# No output on success.
# show command history
$ history
## => output
### [excerpt; numbering and quoting reflect your own session]
### 101 export APP_ENV='production'
### 102 printf '%s\n' "$APP_ENV"
### 103 env
### 104 unset APP_ENV
### 105 history
Press Ctrl+R and type part of an earlier command to search interactively. Press it again to move to an older match.
Quote variable expansions as "$name" unless you intentionally need word splitting or wildcard expansion. Never put passwords or tokens directly into command-line arguments or shell history when a safer secret input mechanism exists.
~/.bashrc configures new interactive Bash shells. Add lines without replacing its existing contents:
# Example additions to ~/.bashrc
export APP_ENV='development'
alias ll='ls --format=long --all --human-readable'
Run source ~/.bashrc to apply the changes to your current shell.
What Did You Learn?
You can now combine command-line tools into pipelines, manage processes and services, inspect system resources, troubleshoot networking, transfer and archive files, work with environment variables and use the package manager for your Linux distribution.
Return to the Ultimate Linux Basics Cheat Sheet for the foundational command reference.
Join Our CommunityYou liked this article? Share it with your colleagues and friends.
Sign up for our newsletter!
Do not miss out on our latest tips, guides, and updates – sign up for our newsletter now! We promise to only send you the most relevant and useful information.
By clicking subscribe, you agree to the privacy policy. You can unsubscribe at any time by clicking the link in the footer of our emails.
