The Text file busy error in specific is about trying to modify an executable while it is executing. The "Text" here refers to the fact that the file being modified is the text segment for a running program.
On Unix-like operating systems text files format is precisely described: POSIX defines a text file as a file that contains characters organized into zero or more lines, where lines are sequences of zero or more non-newline characters plus a terminating newline character, normally LF.
Use the command line to navigate to the Desktop, and then type cat myFile. txt . This will print the contents of the file to your command line. This is the same idea as using the GUI to double-click on the text file to see its contents.
This error means you are trying to modify an executable while it is executing. The "Text" here refers to the fact that the file being modified is the text segment for a running program. Use lsof
to check what other processes are using it. You can use kill
command to kill it if needed.
It's a while since I've seen that message, but it used to be prevalent in System V R3 or thereabouts a good couple of decades ago. Back then, it meant that you could not change a program executable while it was running.
For example, I was building a make
workalike called rmk
, and after a while it was self-maintaining. I would run the development version and have it build a new version. To get it to work, it was necessary to use the workaround:
gcc -g -Wall -o rmk1 main.o -L. -lrmk -L/Users/jleffler/lib/64 -ljl
if [ -f rmk ] ; then mv rmk rmk2 ; else true; fi ; mv rmk1 rmk
So, to avoid problems with the 'text file busy', the build created a new file rmk1
, then moved the old rmk
to rmk2
(rename wasn't a problem; unlink was), and then moved the newly built rmk1
to rmk
.
I haven't seen the error on a modern system in quite a while...but I don't all that often have programs rebuilding themselves.
This occurs when you try and write to a file that is currently being executed by the kernel, or execute a file that is currently open for writing.
Source: http://wiki.wlug.org.nz/ETXTBSY
Minimal runnable C POSIX reproduction example
I recommend understanding the underlying API to better see what is going on.
sleep.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
busy.c
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void) {
int ret = open("sleep.out", O_WRONLY|O_TRUNC);
assert(errno == ETXTBSY);
perror("");
assert(ret == -1);
}
Compile and run:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
passes the asserts, and perror
outputs:
Text file busy
so we deduce that the message is hardcoded in glibc itself.
Alternatively:
echo asdf > sleep.out
makes Bash output:
-bash: sleep.out: Text file busy
For a more complex application, you can also observe it with strace
:
strace ./busy.out
which contains:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Tested on Ubuntu 18.04, Linux kernel 4.15.0.
The error does not happen if you unlink
first
notbusy.c
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void) {
assert(unlink("sleep.out") == 0);
assert(open("sleep.out", O_WRONLY|O_CREAT) != -1);
}
Then compile and run analogously to the above, and those asserts pass.
This explains why it works for certain programs but not others. E.g. if you do:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
that does not generate an error, even though the second gcc
call is writing to sleep.out
.
A quick strace
shows that GCC first unlinks before writing:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
contains:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
The reason it does not fail is that when you unlink
and re-write the file, it creates a new inode, and keeps a temporary dangling inode for the running executable file.
But if you just write
without unlink
, then it tries to write to the same protected inode as the running executable.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
The file is a pure procedure (shared text) file that is being executed and oflag is O_WRONLY or O_RDWR.
man 2 open
ETXTBSY
pathname refers to an executable image which is currently being executed and write access was requested.
glibc source
A quick grep on 2.30 gives:
sysdeps/gnu/errlist.c:299: [ERR_REMAP (ETXTBSY)] = N_("Text file busy"),
sysdeps/mach/hurd/bits/errno.h:62: ETXTBSY = 0x4000001a, /* Text file busy */
and a manual hit in manual/errno.texi
:
@deftypevr Macro int ETXTBSY
@standards{BSD, errno.h}
@errno{ETXTBSY, 26, Text file busy}
An attempt to execute a file that is currently open for writing, or
write to a file that is currently being executed. Often using a
debugger to run a program is considered having it open for writing and
will cause this error. (The name stands for ``text file busy''.) This
is not an error on @gnuhurdsystems{}; the text is copied as necessary.
@end deftypevr
In my case, I was trying to execute a shell file (with an extension .sh) in a csh environment, and I was getting that error message.
just running with bash it worked for me. For example
bash file.sh
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With