Operate the automation

Prevent overlapping runs

Use a lock or launchd lifecycle behavior so two triggers cannot modify the same files simultaneously.

10 minute lesson

~~~

Schedules, Finder actions, and manual retries can overlap. You click the Quick Action while the interval job is mid-run, or a slow run is still working when the next interval fires. Two instances may choose the same destination before either finishes writing, and the result is duplicated or corrupted output that neither run can explain on its own.

launchd gives you one guarantee for free: it does not start a second instance of a label while the first is still running. But that only covers launchd’s own copies. The same script run by hand, or triggered through a Quick Action, is a separate process launchd knows nothing about. For that you need a lock.

macOS does not ship a flock command, so the portable pattern is mkdir, which is atomic: it either creates the directory or fails, with nothing in between.

lock="$HOME/.local/state/screenshot-sorter.lock"

if ! mkdir "$lock" 2>/dev/null; then
  echo "another run holds the lock, exiting" >&2
  exit 0
fi
echo $$ > "$lock/pid"
trap 'rm -rf "$lock"' EXIT

Create a lock atomically, store the owning process information, and remove it on normal exit. The trap releases it even when the script fails partway through.

Verify the lock by simulating the collision:

./sort-screenshots & ./sort-screenshots
# another run holds the lock, exiting

Then handle the crash case. A hard kill can leave the directory behind, and every future run refuses to start. Treat stale-lock recovery as a separate verified path: read $lock/pid, check whether that process is still alive with kill -0, and only then conclude the lock is stale. Do not delete locks blindly at startup; that reintroduces the exact race the lock exists to prevent.

Also decide whether new work should wait, exit, or replace an older run. The example exits, which suits an interval job: the next scheduled run picks up whatever is left. A lock without a documented policy only changes the failure.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →