Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
8 posts found
Your First Bash Script: Shebang, Execute Permission, Exit Codes and When Not to Write a Script
DevOps PART 01

Your First Bash Script: Shebang, Execute Permission, Exit Codes and When Not to Write a Script

A Bash script picks its interpreter with the shebang line, runs thanks to execute permission and talks to its caller through the exit code. With a 10-line script that checks the Bookstore API health endpoint we show the shebang and the dash difference, ./script.sh vs bash vs source, exit codes, the PATH, a script skeleton, the CRLF trap and when a job belongs to Python, PowerShell or a .NET 10 file-based app.

15 Nov 2026 15 min 5
Variables, Quoting and Expansion: Parameter Expansion, Command Substitution, Arrays and the Word Splitting Trap
DevOps PART 02

Variables, Quoting and Expansion: Parameter Expansion, Command Substitution, Arrays and the Word Splitting Trap

In Bash you should always use a variable inside double quotes, because an unquoted value goes through word splitting and globbing, and a file name with a space can get the wrong file deleted. Using Bookstore's health script we show the expansion order, parameter expansion, command substitution and arithmetic, indexed and associative arrays, export and ShellCheck, and explain the rm -rf with an empty variable and macOS Bash 3.2 traps with real output.

15 Nov 2026 15 min 6
Conditionals and Loops: if, [[ ]], case, for, while read and Looping Over Files Safely
DevOps PART 03

Conditionals and Loops: if, [[ ]], case, for, while read and Looping Over Files Safely

In Bash, if looks at a command's exit code rather than a condition; bash scripts use [[ ]], numbers use (( )), reading line by line uses while IFS= read -r, and file names use a glob or find -print0. While writing a bookstore-ctl.sh with subcommands and a cleanup script that keeps the last five releases on the Bookstore server, we show how glob sorting can delete the live release, the file created by > inside [ ] and the counter lost by a while loop in a pipe.

15 Nov 2026 15 min 7
Functions, Arguments and Parsing Options: $@, shift, getopts and a Good --help
DevOps PART 04

Functions, Arguments and Parsing Options: $@, shift, getopts and a Good --help

A Bash function returns data on stdout and success through its exit code; variables inside it are global unless declared local, and scope is dynamic. We collect shared functions in a sourced library and use positional parameters, shift, getopts and a while/case pattern for long options to build Bookstore's bookstore-deploy.sh -e staging -v 1.4.2 --dry-run interface, a good --help text and a dry run based on printf %q.

15 Nov 2026 14 min 6
Data Flow in Scripts: Pipes, Redirection, Here-docs, Process Substitution and xargs
DevOps PART 05

Data Flow in Scripts: Pipes, Redirection, Here-docs, Process Substitution and xargs

In a script, stdout should carry only data and stderr the messages; a pipeline's exit code is its last command's by default and becomes visible with PIPESTATUS and pipefail. We add a log file to Bookstore's deploy script with exec and tee and a RELEASE file with a here-doc, recover the variable a pipe-fed loop loses with < <(...), run work in parallel with xargs -0 -P and produce a JSON report with jq.

15 Nov 2026 18 min 7
Error Handling: How set -euo pipefail Really Behaves, trap, Cleanup, Retry and Locking
DevOps PART 06

Error Handling: How set -euo pipefail Really Behaves, trap, Cleanup, Retry and Locking

set -e does not act on commands whose result is used as a condition, nor inside functions called in such conditions; local x=$(...), command substitution and (( count++ )) surprise too. We add set -Eeuo pipefail, an ERR trap that logs a call stack, an EXIT trap that leaves no half-done folder, retries, timeout, a single-deploy lock with flock and a flow that is safe to run twice to Bookstore's deploy script.

15 Nov 2026 17 min 6
A Real Script: Writing a Deploy and Database Backup Script for Bookstore
DevOps PART 07

A Real Script: Writing a Deploy and Database Backup Script for Bookstore

A reliable deploy script verifies the artifact's checksum, prepares the release outside current, switches current atomically with mv -T instead of ln -sfn and returns to the previous release if the health check fails. We write that deploy for Bookstore, read secrets from env files instead of arguments, and add a verified, rotating SQL Server backup script scheduled with a systemd timer.

15 Nov 2026 19 min 6
Testing Scripts and Making Them Portable: ShellCheck, shfmt, bats-core, CI and From Bash 3.2 on macOS to Bash 5.3
DevOps PART 08

Testing Scripts and Making Them Portable: ShellCheck, shfmt, bats-core, CI and From Bash 3.2 on macOS to Bash 5.3

Bash scripts are linted with ShellCheck, formatted with shfmt and tested with bats-core using stubs placed on PATH, and all three should run in CI on every pull request. We write tests for Bookstore's deploy script and library, wire them into GitHub Actions, and run the same tests on Bash 3.2 on macOS, on Bash 5.3 and on Ubuntu 26.04's Rust coreutils to show where portability breaks.

15 Nov 2026 23 min 6
Blog Map