概述
Text file busy, Linux 系统内核报出的错误之一, errno 26. 可以通过如下方式查看:
$ man error | grep busy
EBUSY Device or resource busy (POSIX.1)
ETXTBSY Text file busy (POSIX.1)
其中 ETXTBSY
就是这个错误.
也可以参考维基百科: errno.h
发生原因
Text file busy 会在如下情况下发生:
- 尝试写入(write)一个正在被执行的文件.
- 尝试执行(execute)一个正在被写入的文件.
英文如下:
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.
refer: ETXTBSY
其中需要注意的是执行(execute)的含义. 一般不加以区分的时候, 可能会认为如下两种情况都叫做执行, 但是含义不尽相同:
# 此例执行的二进制文件是 example.sh
./example.sh
# 此例执行的二进制文件是 sh, 而 example.sh 只是一个参数会被读取
sh example.sh
./example.sh
这种方式是把example.sh
当作二进制可执行文件执行, 只是如果该文件第一行存在 shebang 的话, 会被 Linux 内核识别出来, 然后会自动使用exec
命令重新使用 shebang 中指定的可执行文件重新执行并替换当前进程.sh example.sh
这种方式被执行的二进制文件实际上是sh
, 此时example.sh
只是被当做一个参数传入, 然后 sh 会来读取example.sh
的内容, 所以这个 shell 脚本本身并没有被执行.refer: Why does behavior of './example' and 'sh example' different?
验证
上面提到出现 Text file busy 的原因有两种, 那么我们分别来验证一下.
-
尝试写入(write)一个正在被执行的文件:
# TERMINAL 1 ➜ lane@vbox#2 ~ cat a.c #include <unistd.h> int main() { sleep(60); } ➜ lane@vbox#2 ~ gcc a.c ➜ lane@vbox#2 ~ ./a.out ########################################## ########################################## # TERMINAL 2 # 此时可观察到 FD 是 txt, 说明该文件正在被执行中 ➜ lane@vbox#2 ~ lsof a.out COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME a.out 2692 lane txt REG 253,0 8480 9231359 a.out # 尝试使用写模式打开 a.out, 此时会报错 ➜ lane@vbox#2 ~ python Python 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> open("a.out", "w") Traceback (most recent call last): File "<stdin>", line 1, in <module> IOError: [Errno 26] Text file busy: 'a.out' >>>
- 尝试执行(execute)一个正在被写入的文件.
# 使用 FD 3 以写方式创建一个文件 example ➜ lane@vbox#2 ~ exec 3> example # 查看状态可见 FD 是 3, 且为 write 方式 ➜ lane@vbox#2 ~ lsof example COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME zsh 1479 lane 3w REG 253,0 0 8415983 example # 执行该文件会报错 ➜ lane@vbox#2 ~ chmod u+x example ➜ lane@vbox#2 ~ ./example zsh: text file busy: ./example # sh example 并不会报错, 因为此时被执行的是 sh, 而不是 example ➜ lane@vbox#2 ~ sh example ➜ lane@vbox#2 ~
至此, 两种情况全部验证成功.
Comments