sed: Edit Files Without Opening Them

You need to change a config value across 50 files. You could open each one, or: 1 sed -i 's/old_value/new_value/g' *.conf Done. sed is the stream editor — it transforms text as it flows through. Master it, and you’ll never manually edit repetitive files again. The Basics 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # Replace first occurrence per line echo "hello hello" | sed 's/hello/hi/' # hi hello # Replace all occurrences (g = global) echo "hello hello" | sed 's/hello/hi/g' # hi hi # Replace in file (print to stdout) sed 's/foo/bar/g' file.txt # Replace in place (-i) sed -i 's/foo/bar/g' file.txt # Backup before in-place edit sed -i.bak 's/foo/bar/g' file.txt The -i flag is powerful and dangerous. Always test without it first. ...

February 27, 2026 Â· 5 min Â· 911 words Â· Rob Washington

awk: When grep and cut Aren't Enough

You can grep for lines and cut for columns. But what about “show me the third column of lines containing ERROR, but only if the second column is greater than 100”? That’s awk territory. The Basics awk processes text line by line, splitting each into fields: 1 2 3 4 5 6 7 8 9 # Print second column (space-delimited by default) echo "hello world" | awk '{print $2}' # world # Print first and third columns cat data.txt | awk '{print $1, $3}' # Print entire line awk '{print $0}' file.txt $1, $2, etc. are fields. $0 is the whole line. NF is the number of fields. NR is the line number. ...

February 27, 2026 Â· 6 min Â· 1125 words Â· Rob Washington

find: The Swiss Army Knife You're Underusing

Every developer knows find . -name "*.txt". Few know that find can replace half your shell scripts. Beyond Basic Search 1 2 3 4 5 6 7 8 9 10 11 # Find by name (case-insensitive) find . -iname "readme*" # Find by extension find . -name "*.py" # Find by exact name find . -name "Makefile" # Find excluding directories find . -name "*.js" -not -path "./node_modules/*" The -not (or !) operator is your friend for excluding noise. ...

February 27, 2026 Â· 6 min Â· 1166 words Â· Rob Washington

xargs: Turn Any Output Into Parallel Commands

You have a list of files. You need to process each one. The naive approach: 1 2 3 for file in $(cat files.txt); do process "$file" done This works until it doesn’t — filenames with spaces break it, and it’s sequential. Enter xargs. The Basics xargs reads input and converts it into arguments for a command: 1 2 3 4 5 # Delete files listed in a file cat files.txt | xargs rm # Same thing, more efficient xargs rm < files.txt Without xargs, you’d need a loop. With xargs, one line. ...

February 27, 2026 Â· 5 min Â· 1033 words Â· Rob Washington

Git Hooks: Automate Quality Before It's Too Late

Code review catches problems. CI catches problems. But the fastest feedback loop? Catching problems before you even commit. Git hooks run scripts at key points in your workflow. Use them to lint, test, and validate — automatically. Where Hooks Live 1 2 3 4 5 6 ls .git/hooks/ # applypatch-msg.sample pre-commit.sample # commit-msg.sample pre-push.sample # post-update.sample pre-rebase.sample # pre-applypatch.sample prepare-commit-msg.sample # pre-merge-commit.sample update.sample Remove .sample to activate. Hooks must be executable (chmod +x). ...

February 27, 2026 Â· 6 min Â· 1159 words Â· Rob Washington

Linux Signals: Graceful Shutdowns and Process Control

Your application is running in production. You need to restart it for a config change. Do you: A) kill -9 and hope for the best B) Send a signal it can handle gracefully If you picked A, you’ve probably lost data. Let’s fix that. The Essential Signals Signal Number Default Action Use Case SIGTERM 15 Terminate Graceful shutdown request SIGINT 2 Terminate Ctrl+C, interactive stop SIGHUP 1 Terminate Config reload (by convention) SIGKILL 9 Terminate Force kill (cannot be caught) SIGUSR1/2 10/12 Terminate Application-defined SIGCHLD 17 Ignore Child process state change SIGTERM is the polite ask. “Please shut down when convenient.” SIGKILL is the eviction notice. No cleanup, no saving state, immediate death. ...

February 27, 2026 Â· 5 min Â· 985 words Â· Rob Washington

Cron Jobs That Don't Wake You Up at Night

Cron is deceptively simple. Five fields, a command, done. Until your job runs twice simultaneously, silently fails for a week, or fills your disk with output nobody reads. Here’s how to write cron jobs that actually work in production. The Basics Done Right 1 2 3 4 5 6 7 8 # Bad: No logging, no error handling 0 * * * * /opt/scripts/backup.sh # Better: Redirect output, capture errors 0 * * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1 # Best: Timestamped logging with chronic 0 * * * * chronic /opt/scripts/backup.sh chronic (from moreutils) only outputs when the command fails. Perfect for cron — silent success, loud failure. ...

February 27, 2026 Â· 5 min Â· 896 words Â· Rob Washington

Structured Logging: Stop Grepping, Start Querying

Unstructured logs are a trap. They look simple until you need to find something. [ [ [ 2 2 2 0 0 0 2 2 2 6 6 6 - - - 0 0 0 2 2 2 - - - 2 2 2 7 7 7 0 0 0 5 5 5 : : : 3 3 3 0 0 0 : : : 1 1 1 5 6 7 ] ] ] I E W N R A F R R O O N R U H s F i e a g r i h l j e m o d e h m n t o @ o r e y x p a r u m o s p c a l e g e s e . s c d o o e m r t d e l e c o r t g e g 1 d e 2 : d 3 4 8 i 5 7 n : % f c r o o n m n e 1 c 9 t 2 i . o 1 n 6 8 t . i 1 m . e 5 o 0 u t Quick: find all login failures from a specific IP range in the last hour. Now try parsing the order ID from error messages. Hope you enjoy regex. ...

February 27, 2026 Â· 6 min Â· 1228 words Â· Rob Washington

Shell Scripting Patterns That Prevent 3 AM Pages

Every ops engineer has a story about a shell script that worked perfectly — until it didn’t. Usually at 3 AM. Usually in production. These patterns won’t make your scripts bulletproof, but they’ll stop the most common failures. Start Every Script Right 1 2 3 #!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' This preamble should be muscle memory: set -e: Exit on any error (non-zero return code) set -u: Exit on undefined variables set -o pipefail: Catch errors in pipes (not just the last command) IFS=$'\n\t': Safer word splitting (no spaces) Without these, a typo like rm -rf $UNSET_VAR/ could wipe your root filesystem. ...

February 27, 2026 Â· 5 min Â· 1001 words Â· Rob Washington

Docker Multi-Stage Builds: Smaller Images, Cleaner Deploys

Your Docker images are probably too big. Mine were. Then I learned about multi-stage builds. The problem is simple: build tools bloat production images. You need Node.js and npm to build your React app, but you only need nginx to serve it. You need Go and its toolchain to compile, but the binary runs standalone. Every megabyte of build tooling in your production image is wasted space, slower deploys, and expanded attack surface. ...

February 27, 2026 Â· 4 min Â· 843 words Â· Rob Washington