Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for Automation By James Joyner IV · · 8 min read Last reviewed Jul 2026

flock Error: 'failed to execute /opt/jobs/sync.sh: No such file or directory' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix 'flock: failed to execute ...: No such file or directory' and 'flock: 9: Bad file descriptor' — wrong path, missing +x, shebang, and the -c command form.

  • #automation
  • #troubleshooting
  • #flock
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

flock does two things in sequence: it acquires an advisory lock on a file, and then it execs the command you gave it. This error appears after the lock is successfully taken — the locking worked fine, but flock could not run the command:

$ flock -n /var/lock/sync.lock /opt/jobs/sync.sh
flock: failed to execute /opt/jobs/sync.sh: No such file or directory

The message is precise but easy to misread: the lock was acquired, and the failure is purely about executing /opt/jobs/sync.sh. “No such file or directory” here can mean the file genuinely is not there, or that its shebang points at an interpreter that does not exist — the exec syscall reports both the same way. A different but related error appears when you use the file-descriptor form incorrectly:

$ flock -n 9 /opt/jobs/sync.sh
flock: 9: Bad file descriptor

That one means fd 9 was never opened before flock tried to lock it. Both errors come from misusing flock’s two calling conventions, and both are quick to fix once you know which convention you are in.

Symptoms

  • flock: failed to execute <path>: No such file or directory — lock taken, command not run.
  • flock: failed to execute <path>: Permission denied — the target exists but is not executable.
  • flock: 9: Bad file descriptor when using the flock -n <fd> form.
  • A cron job wrapped in flock silently does nothing, and the cron mail contains one of the lines above.
  • The command runs fine when you type it directly but fails when prefixed with flock.

Common Root Causes

1. Wrong path or a typo in the command

The path passed to flock does not exist — a typo, a wrong directory, or a relative path evaluated from an unexpected working directory (cron runs with a minimal environment and HOME-based cd assumptions may not hold).

2. The target script is not executable

The file exists but lacks the +x bit. flock tries to exec it directly (not through a shell) and gets Permission denied.

3. Missing or wrong shebang interpreter

The script is executable, but its first line names an interpreter that is not installed (#!/usr/bin/python3 with no python3, or a bad path). The kernel’s exec fails with No such file or directory, referring to the interpreter — not the script.

4. Passing a shell builtin, pipeline, or multiple commands

flock lockfile cmd arg execs a single program directly; there is no shell involved. So flock lock 'a | b', flock lock cd /tmp && x, or flock lock echo $VAR do not behave like shell lines. You must use flock -c '<shell command>' for anything that needs a shell.

5. Working-directory assumptions

The script path or a path inside the script is relative, and flock (or cron) runs it from a different directory than you tested in, so a file “disappears.”

6. Using the fd form without opening the descriptor

flock -n 9 ... locks file descriptor 9, but if you never ran exec 9>/var/lock/sync.lock first, fd 9 is closed — hence flock: 9: Bad file descriptor.

How to Diagnose

Confirm the target actually exists at that exact path and is executable:

ls -l /opt/jobs/sync.sh
ls: cannot access '/opt/jobs/sync.sh': No such file or directory

If it is missing, that is your answer. If it exists, check the permission bits and the interpreter:

ls -l /opt/jobs/sync.sh
head -1 /opt/jobs/sync.sh
file /opt/jobs/sync.sh
-rw-r--r-- 1 myuser myuser 512 Jul 12 08:20 /opt/jobs/sync.sh
#!/usr/bin/env python3
/opt/jobs/sync.sh: Python script, ASCII text executable

No x in -rw-r--r-- explains a Permission denied. Now verify the interpreter the shebang names resolves:

command -v python3 || echo "python3 NOT on PATH"
python3 NOT on PATH

A missing interpreter is why an executable script still fails with “No such file or directory.” Run the command exactly as flock would — directly, not through your interactive shell — to reproduce it in isolation:

/opt/jobs/sync.sh
bash: /opt/jobs/sync.sh: No such file or directory

If that direct invocation fails, flock was never the problem. For the fd form, check whether the descriptor was opened:

# This fails because fd 9 is not open in this shell
flock -n 9 echo hi
flock: 9: Bad file descriptor

Fixes

Correct the path, or make the target executable — whichever the diagnosis showed:

chmod +x /opt/jobs/sync.sh
ls -l /opt/jobs/sync.sh
-rwxr-xr-x 1 myuser myuser 512 Jul 12 08:20 /opt/jobs/sync.sh

Fix a broken shebang so it names an interpreter that exists, and install that interpreter if needed:

sed -i '1s|.*|#!/usr/bin/env python3|' /opt/jobs/sync.sh
command -v python3    # must resolve

For anything that needs a shell — pipelines, redirects, variable expansion, or multiple commands — use the -c form so flock invokes a shell:

# Wrong: flock execs 'psql' directly and treats the rest as its args
flock -n /var/lock/sync.lock psql -c 'VACUUM' | tee vac.log

# Right: give flock one shell command to run
flock -n /var/lock/sync.lock -c 'psql -c "VACUUM" | tee /opt/jobs/vac.log'

For the file-descriptor form, open the descriptor first with exec, then lock it — the idiomatic single-instance pattern:

#!/usr/bin/env bash
set -euo pipefail

exec 9>/var/lock/sync.lock
if ! flock -n 9; then
  echo "$(date -Is) another instance holds the lock; skipping" >&2
  exit 0
fi

# critical section runs only when the lock is held
/opt/jobs/sync-impl.sh

In cron, use absolute paths for both the lock file and the command, since cron’s working directory and PATH are minimal:

*/5 * * * * /usr/bin/flock -n /var/lock/sync.lock /opt/jobs/sync.sh >> /var/log/sync.log 2>&1

Verify the fix by running it once by hand and confirming the command actually executes under the lock:

flock -n /var/lock/sync.lock /opt/jobs/sync.sh; echo "exit=$?"
sync complete: 214 records
exit=0

What to Watch Out For

  • The lock is always acquired before the exec fails, so a broken command still holds and releases the lock momentarily — do not assume a failed flock means the lock was never taken.
  • flock cmd execs directly with no shell, so $VAR, |, >, &&, and globs are not interpreted. Reach for flock -c '...' the moment you need any of them.
  • flock -n (non-blocking) exits 1 when the lock is held. Distinguish that expected “already running” exit from a real execution failure by checking the message, not just the exit code.
  • Cron’s environment is not your login shell. A script that runs by hand can fail under cron purely because of a different PATH, HOME, or working directory — use absolute paths everywhere.
  • With exec 9>lockfile, the lock is released when the descriptor closes, which happens automatically when the script exits. Do not rm the lock file to “release” it — that breaks the advisory-lock model and can let two runs proceed.
Free download · 368-page PDF

Fixed it? Get 500 Automation & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.