176

什么操作会产生错误“文本文件忙”?我无法确切地说出。

我认为这与我正在创建一个临时 python 脚本(使用 tempfile)并从中使用 execl 的事实有关,但我认为 execl 会更改正在运行的文件。

4

12 回答 12

183

此错误表示您正在尝试在执行时修改可执行文件。这里的“文本”是指被修改的文件是正在运行的程序的文本段。用于lsof检查其他进程正在使用它。kill如果需要,您可以使用命令将其杀死。

于 2013-05-27T00:30:30.527 回答
32

我已经有一段时间没有看到该消息了,但它曾经在 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,然后将旧文件移动rmkrmk2(重命名不是问题;取消链接是),然后将新构建的文件移动rmk1rmk.

我已经有一段时间没有在现代系统上看到这个错误了……但我并不经常让程序自行重建。

于 2013-05-27T04:09:57.527 回答
26

当您尝试写入内核当前正在执行的文件或执行当前打开以供写入的文件时,会发生这种情况。

资料来源:http ://wiki.wlug.org.nz/ETTXTBSY

于 2017-07-28T11:13:08.223 回答
15

最小可运行 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
于 2018-09-20T14:30:11.803 回答
6

就我而言,我试图在 csh 环境中执行一个 shell 文件(扩展名为 .sh),但我收到了该错误消息。

只是用 bash 运行它对我有用。例如

bash 文件.sh

于 2017-10-02T12:27:58.843 回答
3

如果尝试在 Linux 机器上构建,您可能需要在运行文件之前使用命令phpredis给它时间来完成修改文件权限:sleep

chmod a+x /usr/bin/php/scripts/phpize \
  && sleep 1 \
  && /usr/bin/php/scripts/phpize
于 2017-10-01T14:15:07.870 回答
3

如果您使用 MobaXTerm 等工具从 ssh 连接运行 .sh,并且如果该工具具有自动保存实用程序来从本地计算机编辑远程文件,则会锁定该文件。

关闭并重新打开 SSH 会话可以解决它。

于 2019-03-22T16:04:48.587 回答
2

您可能会发现这在 CIFS/SMB 网络共享上更为常见。Windows 不允许在其他东西打开该文件时写入该文件,即使该服务不是 Windows(它可能是其他一些 NAS 产品),它也可能会重现相同的行为。潜在地,它也可能是一些与锁定/复制模糊相关的潜在 NAS 问题的表现。

于 2016-04-18T22:02:54.283 回答
1

不知道原因,但我可以提供快速简便的解决方法。

cat > shScript.sh在(粘贴,^Z)然后在 KWrite 中编辑文件之后,我刚刚在 CentOS 6 上遇到了这种奇怪的情况。奇怪的是,没有明显ps -ef的脚本执行实例 ( )。

我的快速解决方法很简单,cp shScript.sh shScript2.sh然后我就可以执行了shScript2.sh。然后我把两个都删了。完毕!

于 2014-07-26T14:10:24.840 回答
1

我的经验之一:

我总是通过逆向工程更改 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)
于 2017-03-17T12:53:12.993 回答
0
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
于 2020-07-05T08:46:02.170 回答
0

我在 PHP 中使用文件时遇到了这个问题,然后在使用它之前fopen()尝试了它。unlink()fclose()

不好:

$handle = fopen('file.txt');
// do something
unlink('file.txt');

好的:

$handle = fopen('file.txt');
// do something
fclose($handle);
unlink('file.txt');
于 2015-11-09T20:09:29.110 回答