← All lessons
Linux
All Linux snippets · 196
Every snippet has its own focus page with an explanation and the output it produces.
Files & Directories · 16
- Listing files in detail-l gives the long listing and -h prints sizes in human-readable units.
- Showing hidden filesFiles beginning with a dot are hidden from a plain ls; -a includes them.
- Newest files first-t sorts by modification time, which is the fastest way to find what just changed.
- Returning to the previous directorycd - jumps back to the directory you were in before the last cd.
- Creating nested directories-p creates every missing parent and does not error if the path already exists.
- Copying a directory-r recurses into the directory; without it cp refuses to copy directories.
- Trailing slash changes the targetWhether the destination already exists decides if src lands inside dest or becomes dest.
- Preserving attributes-a preserves ownership, permissions, timestamps and symlinks, which plain -r does not.
- Renaming a filemv renames when the source and destination are in the same directory.
- Overwriting without warningmv silently replaces an existing destination; -i prompts and -n refuses to overwrite.
- rm has no undoThere is no trash can — removed files are gone, so check the path before pressing enter.
- Deleting safely with a prompt-i asks before each deletion, which is worth the extra keystrokes on unfamiliar paths.
- Creating an empty filetouch creates the file if it is missing and updates its timestamp if it exists.
- Inspecting file metadatastat exposes size, owner and permission bits in whatever format you ask for.
- Viewing a directory tree-L limits depth and -d shows directories only, keeping the output readable.
- Splitting a pathbasename strips the directory and dirname strips the filename.
Viewing Files · 9
- Printing a filecat writes the whole file to stdout, which suits short files only.
- First lines of a filehead prints the first ten lines by default; -n changes the count.
- Following a log-f keeps the file open and streams new lines as they are written.
- Following a rotated file-f keeps reading the old inode after logrotate; -F reopens the path when it is replaced.
- Paging through a large fileless pages without loading the whole file, and +F follows it like tail until you press Ctrl-C.
- Counting lines-l counts lines; -w counts words and -c counts bytes.
- Comparing two files-u prints unified context, the same format patches and code reviews use.
- Identifying a file's typefile inspects content rather than the extension, so it catches mislabelled files.
- Verifying a download-c reads the expected checksum from a file and reports whether the data matches.
Permissions & Ownership · 9
- Making a script executable+x sets the execute bit for user, group and others, subject to your umask.
- Octal permission modesEach digit is read(4) + write(2) + execute(1) for owner, group and others.
- 777 is almost never the fixWorld-writable web roots let any local process rewrite your site; fix ownership instead.
- Changing owner and groupThe user and group are separated by a colon, and -R applies down the tree.
- Default permissions for new filesumask masks bits off the default mode, so 027 yields 640 for new files.
- Finding setuid binariesA setuid binary runs as its owner, so an unexpected one is a privilege-escalation risk.
- The sticky bit on /tmpThe trailing t means only a file's owner can delete it, even in a world-writable directory.
- Granting access to one userACLs add per-user rules without changing the file's owner or group.
- Execute bit on directoriesOn a directory the execute bit means traverse, so removing it blocks access to everything inside.
Users & Groups · 8
- Checking your identityid prints your uid, primary group and every supplementary group you belong to.
- Creating a service accountA system account with nologin can own files and run services but cannot be logged into.
- Adding a user to a group-a appends; without it -G replaces every supplementary group the user had.
- Group changes need a new sessionGroup membership is fixed at login, so the new group appears only after you log back in.
- Locking an account-l prefixes the password hash with a bang so it can never match, and -S shows the status.
- Running one command as another user-u targets a specific account instead of root, which is the least-privilege choice.
- su without a dash keeps your environmentWithout the dash you keep the old HOME and PATH; su - starts a proper login shell.
- Looking a user up properlygetent consults every configured source, so it also finds LDAP or SSSD users.
Processes · 13
- Listing processesSorting by memory descending puts the biggest consumers at the top immediately.
- Finding a process by namepgrep matches process names without the grep-matching-itself problem.
- Asking a process to stopPlain kill sends SIGTERM, which lets the process shut down cleanly.
- kill -9 skips cleanupSIGKILL cannot be caught, so buffers go unflushed and lock files are left behind.
- Signalling by name and user-f matches the full command line, which is essential for interpreter processes.
- Watching live resource use-b with -n 1 makes top scriptable instead of interactive.
- Backgrounding and resuming& starts a job in the background, jobs lists them and fg brings one forward.
- Surviving a disconnectnohup detaches the process from the terminal so a dropped SSH session does not kill it.
- Background jobs die with the shellA plain background job still belongs to the shell; use nohup, setsid or a systemd unit.
- Finding what holds a portlsof maps open files and sockets back to the process that owns them.
- Deleted files still consume diskA deleted file keeps its blocks until the last file descriptor closes, so df stays full.
- Tracing system callsTracing openat shows exactly which files a process is trying to read.
- Lowering a job's priorityA higher nice value yields CPU to everything else, keeping background work out of the way.
systemd · 12
- Service statusstatus shows whether the unit is active, its PID and the last few log lines.
- Starting and enabling a serviceenable sets it to start at boot and --now starts it immediately.
- enable is not startenable only affects the next boot; without --now the service is still down.
- Reloading after a unit editsystemd caches unit files, so an edit has no effect until daemon-reload runs.
- A minimal service unitThree sections describe ordering, how to run the process and when to enable it.
- Hardening a unitsystemd can sandbox a service without containers, restricting writes and privilege gain.
- Listing failed unitsA quick health check after a reboot or a bad deploy.
- Reading a service's logs-u filters to one unit and -n limits how far back it reads.
- Logs since a point in time-p filters by priority, so you see only errors and worse.
- Logs vanish after rebootWithout Storage=persistent the journal lives in /run and is lost on every reboot.
- A systemd timer instead of cronPersistent=true runs a missed job after the machine comes back up, which cron will not do.
- Finding slow boot unitsblame ranks units by how long they delayed the boot.
Pipes & Redirection · 11
- Chaining commandsEach pipe feeds the previous command's stdout into the next command's stdin.
- Writing and appending> truncates the file while >> appends to it.
- Redirecting stderr2> redirects file descriptor 2, silencing permission-denied noise.
- Order of 2>&1 matters2>&1 copies wherever stdout points at that moment, so putting it first leaves stderr on the terminal.
- Seeing and saving outputtee writes to the file and passes the stream on, so you keep the live view.
- Writing to a root-owned filesudo applies to tee, not to the redirect, which is why sudo echo > file fails.
- Turning input into arguments-print0 and -0 pair up so filenames containing spaces survive the handoff.
- Running jobs in parallel-P runs several invocations concurrently, which speeds up IO-bound batches.
- Feeding a block of textQuoting the delimiter stops the shell expanding variables inside the block.
- Comparing two command outputsProcess substitution gives each command a file-like handle, so diff can read both.
- Discarding all outputEverything written to /dev/null is thrown away, silencing a command entirely.
Text Processing · 18
- Searching a file-n prefixes each match with its line number.
- Recursive case-insensitive search-r walks the tree, -i ignores case and --include limits it to one file type.
- Showing context around matches-C prints lines either side of each match, which is what makes a stack trace readable.
- Inverting and counting-v keeps non-matching lines and -c counts them instead of printing.
- Extended regex-E enables extended regex so alternation and grouping work without backslashes.
- Substituting texts/old/new/g replaces every occurrence on each line and prints the result.
- In-place edits need -iWithout -i sed only prints the change; the file on disk is untouched.
- Editing in place with a backup-i.bak rewrites the file and keeps the original alongside it.
- Printing a line range-n suppresses default output so only the explicitly printed range appears.
- Selecting a columnawk splits on whitespace and exposes each field as $1, $2 and so on.
- Filtering and summingA pattern-action pair runs per line, and END runs once after the last one.
- Grouping with an arrayAssociative arrays make awk a one-line group-by over log data.
- Extracting a delimited field-d sets the delimiter and -f picks the fields to keep.
- Numeric sort-h understands human-readable suffixes and -r reverses the order.
- uniq only collapses adjacent linesuniq compares neighbours only, so the input must be sorted first.
- Translating characterstr maps characters one to one, which is the cheapest way to change case.
- Aligning output into columnscolumn -t aligns whitespace-separated input into a readable table.
- Querying JSON outputjq parses JSON properly instead of guessing with grep, and -r drops the quotes.
Search & Find · 7
- Finding files by name-name matches the filename and -type f restricts results to regular files.
- Finding large files-size filters by size and -exec runs a command per match, with {} as the filename.
- Deleting old files-mtime +14 matches files modified more than fourteen days ago.
- -exec runs one process per fileEnding with + batches the arguments instead of forking once per file, which is far faster.
- Combining conditionsParentheses group the alternatives and -mmin filters by minutes rather than days.
- Locating a commandcommand -v is the portable form and also resolves aliases and shell builtins.
- locate reads a stale indexlocate queries a database built by a cron job, so new files are missing until updatedb runs.
Archives & Transfer · 11
- Creating a compressed archivec creates, z compresses with gzip and f names the output file.
- Extracting to a directoryx extracts and -C changes into the target directory first.
- Listing an archive before extractingt lists the contents, which is worth checking before unpacking into a live path.
- Archives can contain absolute pathsAn archive built with absolute paths can overwrite system files; extract into a scratch dir first.
- Mirroring a directoryThe trailing slash on the source copies its contents, and --delete removes extras at the target.
- The trailing slash changes everythingWithout the trailing slash the directory itself is copied, creating a nested path.
- Resuming a large transfer-P keeps partial files and shows progress, so an interrupted transfer resumes.
- Copying a file over SSHscp uses your SSH credentials and config, so no extra setup is needed.
- Checking an endpoint-w formats a summary line, which makes curl a quick uptime probe.
- Posting JSON-d sends a request body and implies POST unless -X says otherwise.
- Downloading a filewget writes to a file by default, where curl writes to stdout.
Disk & Filesystem · 10
- Checking free space-h is human readable and -T adds the filesystem type.
- Finding what fills a directory-s summarises each argument rather than listing every file underneath.
- Disk full but du disagreesRunning out of inodes fills the filesystem while the byte count still looks fine.
- Listing block devices-f adds the filesystem type, label and UUID for each device.
- Mounting a diskfindmnt confirms what actually got mounted and with which options.
- Persisting a mountUsing the UUID rather than /dev/sdb1 survives device reordering across reboots.
- A bad fstab blocks bootmount -a validates every entry now, rather than discovering the mistake at the next boot.
- Creating a symlink-s makes a symbolic link, which points at a path rather than the underlying inode.
- Hard links share the inodeA hard link is the same file, so a write through one name is visible through the other.
- Flushing writes to disksync commits dirty pages before the cache is dropped, which is how you benchmark cold reads.
Networking · 12
- Showing addresses-brief condenses the output to one line per interface.
- Viewing the routing tableThe default route names the gateway every non-local packet goes through.
- Listing listening portsss replaces netstat: t and u pick TCP and UDP, l listens, p names the process.
- Counting connections by stateA quick way to spot a pile-up of TIME-WAIT or CLOSE-WAIT sockets.
- Resolving a name+short strips everything but the answer, which is what scripts want.
- Querying a specific resolverAsking a public resolver directly bypasses local caching and confirms what the world sees.
- Testing reachability-c limits the count so the command exits instead of running forever.
- ICMP blocked is not downPlenty of hosts drop ICMP while serving traffic normally; test the actual port instead.
- Testing a TCP port-z scans without sending data, which answers whether the port accepts connections.
- Overriding DNS locally/etc/hosts wins over DNS for most resolvers, which is handy for local testing.
- Allowing a port through the firewallufw is a friendly front end over the kernel's netfilter rules.
- Capturing traffic on a port-nn skips name resolution so the capture keeps up and shows raw addresses.
SSH & Remote · 8
- Connecting to a host-p selects a non-default port, which many hardened hosts use.
- Creating a key paired25519 keys are short, fast and the current default recommendation.
- Installing your public keyThis appends the key to the remote authorized_keys with the right permissions.
- Naming a connectionAn entry in ~/.ssh/config turns a long command into ssh web.
- Key permissions are enforcedSSH refuses to use a private key that other users can read.
- Tunnelling a remote port-L forwards a local port to a service reachable from the remote host, and -N skips the shell.
- Running a command remotelyQuoting the command keeps the local shell from expanding it before it is sent.
- Reusing connectionsConnection multiplexing makes every subsequent ssh to the same host near-instant.
Shell Scripting · 16
- Assigning and expandingNo spaces are allowed around the equals sign, and braces disambiguate the expansion.
- Unquoted variables splitWord splitting turns one filename into two arguments; always quote the expansion.
- Default values:- supplies a fallback when the variable is unset or empty.
- Testing a file-f is true when the path exists and is a regular file.
- String and numeric tests[[ ]] adds pattern matching and safer operators than the older [ ] form.
- Looping over filesThe glob expands to a list before the loop runs, so no subshell is needed.
- Reading a file line by lineIFS= and -r keep leading whitespace and backslashes intact.
- Defining a function$* joins all arguments, and functions see them as $1, $2 and so on.
- Checking the last exit code$? holds the exit status of the previous command; zero means success.
- Failing fast in a script-e exits on error, -u on undefined variables and pipefail on any failing pipe stage.
- set -e ignores failures in conditionsCommands tested by if or joined with || are exempt, which is usually what you want but surprises people.
- Cleaning up on exitAn EXIT trap runs however the script ends, including on error or interrupt.
- Requiring an argument$# is the argument count and >&2 sends the usage message to stderr.
- Iterating an array safelyQuoting ${arr[@]} preserves each element as a single word.
- Capturing output$( ) captures stdout and nests more cleanly than backticks.
- Linting a scriptshellcheck catches quoting and portability bugs that only bite in production.
Environment & Shell · 9
- Exporting a variableOnly exported variables are inherited by child processes.
- Variables do not escape a subshellA child process cannot change its parent's environment, which is why scripts are sourced.
- Adding to PATHEarlier entries win, so prefixing overrides a system-installed version.
- Loading variables into the current shellset -a exports everything assigned while it is active, which is the usual .env trick.
- Creating a shortcutAliases live in the interactive shell only and are not seen by scripts.
- Searching your historyCtrl-R does the same interactively and is faster once it is muscle memory.
- Secrets land in historyA leading space keeps the line out of history when HISTCONTROL allows it.
- Running with a modified environmentenv sets variables for one command without touching the current shell.
- Identifying your shell$SHELL is your login shell, while $$ resolves to the shell actually running.
Package Management · 7
- Installing a packageupdate refreshes the index; installing without it can pull a stale version reference.
- Finding which package owns a filedpkg -S maps a path back to the package that installed it.
- Listing a package's filesUseful when you need to know where a package put its config.
- remove leaves configuration behindremove keeps config files; purge deletes them too.
- Holding a package versionA hold stops unattended upgrades moving a version you have pinned deliberately.
- Installing on RHEL familydnf is the Fedora and RHEL equivalent of apt, with rpm as the low-level tool.
- Checking what will be upgradedReviewing the list before upgrading avoids surprise restarts of production services.
Cron & Scheduling · 6
- Editing your crontab-e opens your personal crontab and -l prints it without opening an editor.
- Cron schedule fieldsThe five fields are minute, hour, day of month, month and day of week.
- Cron has a minimal PATHCron does not read your profile, so use absolute paths and redirect the output.
- Preventing overlapping runsflock -n skips the run instead of stacking a second copy on a slow job.
- Scheduling a one-off jobat handles single future runs, where cron handles repetition.
- System-wide cron jobsPackages drop scheduled jobs here, with an extra user field in /etc/cron.d entries.
Monitoring & Performance · 8
- Load averageThe three numbers are the one, five and fifteen minute run-queue averages.
- Free memory looks low on purposeLinux uses spare RAM as cache; the available column is the number that matters.
- Spotting swap pressureSustained non-zero si and so columns mean the machine is swapping and needs more RAM.
- Checking disk latency%util near 100 with a high await points at the disk as the bottleneck.
- Reading kernel messages-T converts timestamps to readable dates, which raw dmesg does not do.
- The OOM killer picks a victimWhen memory runs out the kernel kills a process; the service just disappears with no error of its own.
- Re-running a commandwatch repeats a command on an interval and highlights what changed.
- Counting CPUs before reading loadA load average of 4 is saturated on two cores and idle on sixteen, so context matters.
Signals & Job Control · 6
- Listing available signalsSignals are numbered, and the names are what scripts should use for clarity.
- Reloading config without downtimeMany daemons reread their configuration on SIGHUP instead of restarting.
- Suspending and resumingCtrl-Z suspends the foreground job and bg resumes it in the background.
- Detaching a running jobdisown -h shields an already-running job from the HUP sent when the shell exits.
- Bounding a command's runtimetimeout kills the command after the deadline and exits 124, which scripts can detect.
- Keeping a session aliveA tmux session survives disconnection, so a dropped SSH link does not kill the work.