Shell Scripting Style

Conventions for bash/shell code and one-off commands, in scripts or ad-hoc terminal use.

Variable case: lowercase for locals, UPPERCASE only for environment

Use lowercase (or snake_case) for ordinary shell variables: block=$(cat file.json), not BLOCK=$(cat file.json). Reserve all-caps names for variables that are actually exported as environment variables (export PATH=..., NOTES_URL read by a script via os.getenv, etc.) or that are genuine shell built-ins/conventions (HOME, PATH).

Why: all-caps is the long-standing convention for environment variables specifically. Using it for a plain local variable (a temp holder for a JSON blob, a loop counter, a path) is misleading -- it signals "this is exported / read by another process" when it isn't.

pkill -f can match its own command (self-kill). pkill -f keepalive.py matches every process whose command line contains “keepalive.py” — including the shell running the pkill itself, because that string is in its argv. The command then kills itself mid-run (no output, odd exit code). Use a regex that breaks the literal substring (pkill -f 'keepalive[.]py' — the [.] means the pattern text isn’t a literal match for its own cmdline) or kill by PID from pgrep. Relatedly, backgrounding a process inside a captured or SSH command can swallow the command’s output or hold the channel open — detach fully (setsid … </dev/null >/dev/null 2>&1 & disown) and verify the result in a separate call.

Validate against the deployed shell, not only the development shell. A clean bash -n check proves syntax parsing on the shell that ran it; it does not prove that an older target Bash supports every builtin option. For remote operational scripts, identify the target Bash version or avoid newer features when a portable loop is simple. Treat compatibility failures as fail-safe only if they occur before mutation, and make retry work areas unique so a stopped preparation can be retained rather than overwritten.

version 3  ·  updated 2026-09-12