Safe, robust Bash script: error handling, locking, logs and dry-run

Generate a server-ready Bash script: strict mode, trap cleanup, getopts argument parsing, a lock against concurrent runs, logging, dry-run mode and ShellCheck-clean code. Designed for ChatGPT, Claude, Gemini and Microsoft Copilot. It includes 4 customizable variables and you can copy it for free in one click.

Intermediate · Code · Pending editorial review

Prompt

Act as a Linux systems administrator who writes maintainable, safe shell scripts.

I need a script that does the following: {{task}}
- Environment it will run in: {{environment}}
- Inputs (arguments, files, variables): {{inputs}}
- What it modifies or deletes: {{effects}}

Deliverables:
1. The complete script with:
   - A shebang suited to the environment and strict mode (`set -Eeuo pipefail`) or its equivalent if the shell is not Bash, explaining its gotchas.
   - A `usage` function and argument parsing with `getopts`, including `-h`, `-v` (verbose) and `-n` (dry-run).
   - A dependency check with `command -v` and clear messages when something is missing.
   - Variables always quoted, `local` inside functions and no `eval`.
   - Temp files via `mktemp` and cleanup with `trap` on `EXIT`, `INT` and `TERM`.
   - A lock with `flock` (or a portable alternative) to prevent two simultaneous runs.
   - Timestamped logs to stderr and optionally to a file.
   - Documented exit codes.
   - In dry-run mode, print what it would do without running anything destructive.
2. An explanation of each block and of any dangerous line (deletions, permissions, `sudo`).
3. How to verify it: ShellCheck with no warnings, plus a few bats-core tests or a manual procedure in a scratch directory.
4. How to schedule it with cron or a systemd timer if that makes sense, including the PATH and variables it needs.

Constraints:
- Any `rm` or overwrite must first check that the path is not empty and not `/`.
- Do not invent paths or server names: use mine or [FILL IN].
- If the task is ambiguous or dangerous, ask me before writing the script.
- Recommend testing with `-n` first and outside production.

How to use it

  1. Describe the task step by step the way you would do it by hand.
  2. Name the exact system (distro, macOS or container) because it changes the available shell.
  3. Run ShellCheck, execute with -n and review the output before dropping dry-run.

Usage example

Task: compress logs older than 7 days in /var/log/myapp and delete ones older than 30 · Environment: Ubuntu 24.04 with Bash 5 · Effects: deletes old files.

Sample output

1. Script

#!/usr/bin/env bash
# rotate-logs.sh — compress .log older than N days, delete .gz older than M days
set -Eeuo pipefail

LOG_DIR="/var/log/myapp"; COMPRESS_DAYS=7; DELETE_DAYS=30
DRY_RUN=0; VERBOSE=0; LOCK="/run/lock/rotate-logs.lock"

log()   { printf '%s [%s] %s\n' "$(date '+%F %T')" "$1" "$2" >&2; }
usage() { echo "Usage: ${0##*/} [-h] [-v] [-n] [-d dir] [-c days] [-r days]"; }
run()   { if (( DRY_RUN )); then log DRY "$*"; return 0; fi
          if (( VERBOSE )); then log INFO "$*"; fi; "$@"; }

while getopts ":hvnd:c:r:" opt; do
  case "$opt" in
    h) usage; exit 0 ;;  v) VERBOSE=1 ;;  n) DRY_RUN=1 ;;
    d) LOG_DIR="$OPTARG" ;;  c) COMPRESS_DAYS="$OPTARG" ;;  r) DELETE_DAYS="$OPTARG" ;;
    *) usage; exit 1 ;;
  esac
done

# Never operate on an empty path or on /
[[ -n "$LOG_DIR" && "$LOG_DIR" != "/" && -d "$LOG_DIR" ]] || { log ERROR "invalid directory: $LOG_DIR"; exit 2; }
[[ "$COMPRESS_DAYS$DELETE_DAYS" =~ ^[0-9]+$ ]] || { log ERROR "days must be integers"; exit 1; }
command -v gzip >/dev/null || { log ERROR "gzip is missing"; exit 3; }

exec 9>"$LOCK"; flock -n 9 || { log WARN "another run is in progress"; exit 4; }

find "$LOG_DIR" -type f -name '*.log' -mtime +"$COMPRESS_DAYS" -print0 |
  while IFS= read -r -d '' f; do run gzip -- "$f"; done
find "$LOG_DIR" -type f -name '*.gz' -mtime +"$DELETE_DAYS" -print0 |
  while IFS= read -r -d '' f; do run rm -f -- "$f"; done

-print0 with read -d '' handles file names with spaces, and -- stops a file starting with a dash from being read as an option. Run ./rotate-logs.sh -n -v first and put it through ShellCheck…

Key facts

Category
Programming & development · Automations
Output type
Code
Level
Intermediate
Designed for
ChatGPT, Claude, Gemini and Microsoft Copilot
Verified in
Pending editorial verification
Variables
Task, Environment, Inputs and What it modifies or deletes
Language
English
Price
Free, no sign-up
Updated
Nov 7, 2026

Frequently asked questions

What exactly does set -Eeuo pipefail do?

It stops the script on an error (-e), on unset variables (-u) and when any command in a pipeline fails (pipefail); -E passes the ERR trap into functions. It has exceptions, which is why the prompt asks for them to be explained.

Why use flock in a scheduled script?

It prevents two runs from overlapping when the previous one has not finished yet, which is common with cron. Without a lock, two copies can clobber each other's files or duplicate work.

What is this prompt for?

Generate a server-ready Bash script: strict mode, trap cleanup, getopts argument parsing, a lock against concurrent runs, logging, dry-run mode and ShellCheck-clean code.

Which AI tools does it work with?

It is designed for ChatGPT, Claude, Gemini and Microsoft Copilot. We have not verified it in these tools yet, so results may vary between them.

How do I customize the prompt?

Click “Customize” and fill in the variables (Task, Environment, Inputs and What it modifies or deletes). The text updates instantly and you can then copy it in one click. Values are stored only in your browser.

Do I need experience to use it?

It is intermediate: it helps to know the topic so you can provide good context and review the result critically.

Is this prompt free?

Yes. Every HomeCasa Prompts prompt is free, with no sign-up or subscription. You can also use them in professional projects.

Can I trust the AI output?

Treat it as a high-quality draft: always check data, figures and important claims before publishing or making decisions.

Related prompts