什么操作会产生错误“文本文件忙”?我无法确切地说出。
我认为这与我正在创建一个临时 python 脚本(使用 tempfile)并从中使用 execl 的事实有关,但我认为 execl 会更改正在运行的文件。
什么操作会产生错误“文本文件忙”?我无法确切地说出。
我认为这与我正在创建一个临时 python 脚本(使用 tempfile)并从中使用 execl 的事实有关,但我认为 execl 会更改正在运行的文件。
此错误表示您正在尝试在执行时修改可执行文件。这里的“文本”是指被修改的文件是正在运行的程序的文本段。用于lsof
检查其他进程正在使用它。kill
如果需要,您可以使用命令将其杀死。
我已经有一段时间没有看到该消息了,但它曾经在 System V R3 或大约几十年前盛行。那时,这意味着您无法在运行时更改程序可执行文件。
例如,我正在构建一个make
名为的类似工作rmk
,一段时间后它就可以自我维护了。我会运行开发版本并让它构建一个新版本。为了让它工作,有必要使用解决方法:
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
因此,为了避免“文本文件繁忙”出现问题,构建创建了一个新文件rmk1
,然后将旧文件移动rmk
到rmk2
(重命名不是问题;取消链接是),然后将新构建的文件移动rmk1
到rmk
.
我已经有一段时间没有在现代系统上看到这个错误了……但我并不经常让程序自行重建。
当您尝试写入内核当前正在执行的文件或执行当前打开以供写入的文件时,会发生这种情况。
最小可运行 C POSIX 再现示例
我建议了解底层 API 以更好地了解发生了什么。
睡眠.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
忙碌的.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);
}
编译并运行:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
传递断言,并perror
输出:
Text file busy
所以我们推断消息是在 glibc 本身中硬编码的。
或者:
echo asdf > sleep.out
使 Bash 输出:
-bash: sleep.out: Text file busy
对于更复杂的应用程序,您还可以通过以下方式观察它strace
:
strace ./busy.out
其中包含:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
在 Ubuntu 18.04、Linux 内核 4.15.0 上测试。
unlink
如果您首先发生错误,则不会发生
不忙.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);
}
然后类似于上面的编译和运行,那些断言通过了。
这解释了为什么它适用于某些程序而不适用于其他程序。例如,如果你这样做:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
这不会产生错误,即使第二次gcc
调用正在写入sleep.out
.
快速strace
显示 GCC 在写入之前首先取消链接:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
包含:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
它没有失败的原因是当你unlink
重写文件时,它会创建一个新的 inode,并为正在运行的可执行文件保留一个临时的悬空 inode。
但是,如果您只是write
没有unlink
,那么它会尝试写入与正在运行的可执行文件相同的受保护的 inode。
POSIX 7open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
该文件是正在执行的纯过程(共享文本)文件,oflag 为 O_WRONLY 或 O_RDWR。
男人 2 打开
ETXTBSY
路径名是指当前正在执行并请求写访问的可执行映像。
glibc 源码
2.30 上的快速 grep 给出:
sysdeps/gnu/errlist.c:299: [ERR_REMAP (ETXTBSY)] = N_("Text file busy"),
sysdeps/mach/hurd/bits/errno.h:62: ETXTBSY = 0x4000001a, /* Text file busy */
并手动点击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
就我而言,我试图在 csh 环境中执行一个 shell 文件(扩展名为 .sh),但我收到了该错误消息。
只是用 bash 运行它对我有用。例如
bash 文件.sh
如果尝试在 Linux 机器上构建,您可能需要在运行文件之前使用命令phpredis
给它时间来完成修改文件权限:sleep
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
如果您使用 MobaXTerm 等工具从 ssh 连接运行 .sh,并且如果该工具具有自动保存实用程序来从本地计算机编辑远程文件,则会锁定该文件。
关闭并重新打开 SSH 会话可以解决它。
您可能会发现这在 CIFS/SMB 网络共享上更为常见。Windows 不允许在其他东西打开该文件时写入该文件,即使该服务不是 Windows(它可能是其他一些 NAS 产品),它也可能会重现相同的行为。潜在地,它也可能是一些与锁定/复制模糊相关的潜在 NAS 问题的表现。
不知道原因,但我可以提供快速简便的解决方法。
cat > shScript.sh
在(粘贴,^Z
)然后在 KWrite 中编辑文件之后,我刚刚在 CentOS 6 上遇到了这种奇怪的情况。奇怪的是,没有明显ps -ef
的脚本执行实例 ( )。
我的快速解决方法很简单,cp shScript.sh shScript2.sh
然后我就可以执行了shScript2.sh
。然后我把两个都删了。完毕!
我的经验之一:
我总是通过逆向工程更改 Chrome 的默认键盘快捷键。修改后忘记关闭Chrome,运行如下:
sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
使用 strace,您可以找到更多详细信息:
sudo strace cp ./chrome /opt/google/chrome/chrome 2>&1 |grep 'Text file busy'
open("/opt/google/chrome/chrome", O_WRONLY|O_TRUNC) = -1 ETXTBSY (Text file busy)
root@h1:bin[0]# mount h2:/ /x
root@h1:bin[0]# cp /usr/bin/cat /x/usr/local/bin/
root@h1:bin[0]# umount /x
...
root@h2:~[0]# /usr/local/bin/cat
-bash: /usr/local/bin/cat: Text file busy
root@h2:~[126]#
ubuntu 20.04, 5.4.0-40-generic
nfsd problem, after reboot ok
我在 PHP 中使用文件时遇到了这个问题,然后在使用它之前fopen()
尝试了它。unlink()
fclose()
不好:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
好的:
$handle = fopen('file.txt');
// do something
fclose($handle);
unlink('file.txt');