Add lockfile to prevent concurrent immich-sync runs

- Creates ~/.immich-sync.lock with PID on start
- Checks if existing lock's process is still running (stale lock detection)
- Logs clear message when skipping due to active lock
- Releases lock on exit via trap (handles success and failure)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-01-26 12:34:55 -08:00
commit df32bc8f82

View file

@ -18,6 +18,7 @@ DOCKER=/usr/local/bin/docker
EXPORT_DIR="{{ immich_sync_export_dir }}"
IMMICH_URL="{{ immich_sync_url }}"
API_KEY_FILE="$HOME/.immich-api-key"
LOCKFILE="$HOME/.immich-sync.lock"
LOG_PREFIX="[immich-sync]"
log() {
@ -28,6 +29,43 @@ error() {
echo "$LOG_PREFIX $(date '+%Y-%m-%d %H:%M:%S') ERROR: $*" >&2
}
# Lockfile management to prevent concurrent runs
acquire_lock() {
if [[ -f "$LOCKFILE" ]]; then
local lock_pid lock_time
lock_pid=$(cat "$LOCKFILE" 2>/dev/null | head -1)
lock_time=$(stat -f %Sm -t '%Y-%m-%d %H:%M:%S' "$LOCKFILE" 2>/dev/null || echo "unknown")
# Check if the process is still running
if [[ -n "$lock_pid" ]] && kill -0 "$lock_pid" 2>/dev/null; then
error "Another sync is already running (PID: $lock_pid, started: $lock_time)"
error "Lockfile: $LOCKFILE"
error "If this is stale, remove the lockfile manually: rm $LOCKFILE"
exit 0 # Exit cleanly so LaunchAgent doesn't report failure
else
log "WARNING: Found stale lockfile from PID $lock_pid (process not running), removing it"
rm -f "$LOCKFILE"
fi
fi
# Create lockfile with our PID
echo $$ > "$LOCKFILE"
log "Acquired lock (PID: $$)"
}
release_lock() {
if [[ -f "$LOCKFILE" ]]; then
rm -f "$LOCKFILE"
log "Released lock"
fi
}
# Ensure lock is released on exit (success or failure)
trap release_lock EXIT
# Acquire lock before doing anything else
acquire_lock
# Check prerequisites
if [[ ! -x "$MISE" ]]; then
error "mise not found at $MISE"