Linux Error: Text file busy — Cause, Fix, and Troubleshooting Guide
How to fix the Linux 'Text file busy' (ETXTBSY) error: find the process running or holding a binary with lsof and fuser, stop it, then replace or overwrite the executable safely.
- #linux
- #troubleshooting
- #processes
Summary
Text file busy maps to ETXTBSY (26). Here “text” is the old Unix term for a program’s executable code segment, not a text document. The kernel returns it when you try to write to or replace an executable that is currently being run (or is open for writing while running). Linux refuses to let you modify the on-disk image of a running program in place, so a build or deploy that overwrites a live binary fails.
Common Symptoms
- A deploy or
cp/install/go build -ofails withtext file busywhen writing the output binary. mv new-binary /usr/local/bin/appworks butcp new-binary /usr/local/bin/appfails while the app is running.- A compiler/linker fails to write its output because the previous run of that binary is still executing.
- Overwriting a shared library or script interpreter that a running process has mapped fails.
Most Likely Causes of the ‘Text file busy’ Error
Common production causes of the Text file busy error:
- Overwriting a running binary in place —
cp/installtargets the exact path of a process that is currently executing. - A build writing over its own still-running output — a previous invocation of the just-built program has not exited.
- A supervisor/systemd service still running the old binary during an in-place upgrade.
- A lingering or zombie-parent process holding the executable open long after it should have exited.
- A background/detached copy of the program (cron job, watchdog) keeping the image mapped.
Quick Triage
# Which processes are running or holding this binary open?
fuser -v /usr/local/bin/app
# Same, with full detail via lsof
lsof /usr/local/bin/app
# Is a systemd service tied to it?
systemctl status app 2>/dev/null | head
Any PID that fuser/lsof reports against the target path is why the write is refused — that process must stop (or you must swap the file via rename, not overwrite).
Diagnostic Commands
# fuser: shows PIDs; access type 'e' means running as this executable
fuser -v /usr/local/bin/app
# lsof: list every process with the file open (txt = mapped executable text)
lsof /usr/local/bin/app
lsof -w /usr/local/bin/app | awk '$4 ~ /txt/'
# Map a PID back to its executable to confirm it's the same file
ls -l /proc/<PID>/exe
# Find all processes whose executable is (a deleted copy of) this path
for p in /proc/[0-9]*; do
[ "$(readlink "$p/exe")" = "/usr/local/bin/app" ] && echo "${p##*/}"
done
# Confirm the mount isn't the issue (rare: noexec/remount)
findmnt -T /usr/local/bin
lsof marking the file as txt (text/executable) for a PID is the definitive sign that process is running that exact image and holding ETXTBSY.
Fix / Remediation
The safe, zero-downtime fix is to replace the file by atomic rename rather than overwriting it — a running process keeps its old inode, and new starts pick up the new file.
-
Write to a temp path, then
mvover the target (rename is atomic on the same filesystem and does not touch the running inode):cp new-app /usr/local/bin/app.new mv -f /usr/local/bin/app.new /usr/local/bin/app -
Or unlink first, then write — same effect, the running process holds the now-unnamed old inode:
rm -f /usr/local/bin/app cp new-app /usr/local/bin/app -
Restart the service so it execs the new binary (the old inode is freed on exit):
sudo systemctl restart app -
For a build overwriting its own output, ensure the prior run has exited:
fuser -k -TERM ./mytool 2>/dev/null # graceful stop of stragglers go build -o mytool . -
Stop the holding process gracefully if a rename isn’t possible:
sudo systemctl stop app # or: kill -TERM <PID> # replace the binary, then start again
Warning:
kill -9 <PID>(SIGKILL) orfuser -k -KILLforce-terminates the process with no cleanup — it can corrupt in-flight state or drop connections. Prefer atomic rename (step 1) which needs no kill at all, or a gracefulSIGTERM/systemctl stopfirst; use-9only as a last resort on a truly stuck process.
Validation
# No process holds the path anymore (or it's the new inode)
fuser -v /usr/local/bin/app
ls -l /usr/local/bin/app # size/mtime match the new binary
/usr/local/bin/app --version # runs the replacement
An empty fuser result (or a PID whose /proc/<PID>/exe now points at the new inode) plus the new version string confirms the swap succeeded.
Prevention
- Deploy binaries by writing to a temp file and atomically
mv-ing over the target on the same filesystem — this never hitsETXTBSY. - Use symlink-swap releases (
app -> releases/v2/app) and repoint the link, so the live inode is never overwritten. - Package managers (
apt,dnf) already replace files via rename — prefer them over hand-cpfor system binaries. - In CI, name build outputs uniquely or stop prior runs before rebuilding to the same path.
- Restart the service after replacement so it stops running the freed old inode.
Related Errors
Final Notes
Text file busy is ETXTBSY: Linux will not let you overwrite the on-disk image of an executable that is currently running. Use fuser/lsof to find the holding PID, then avoid the whole problem by replacing the file with an atomic rename (write temp, mv over) instead of an in-place overwrite — the running process keeps its old inode and the next start picks up the new one. Reserve kill -9 for genuinely stuck processes; graceful stop or rename is almost always enough.
Want faster Linux incident response? Use DevOps AI Toolkit to turn production errors into clear diagnostics, remediation steps, and reusable runbooks.
Download the Free 500-Prompt DevOps AI Toolkit
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.