什么在Unix中生成"文本文件忙"消息?

Pen*_*enz 126 unix

什么操作生成错误"文本文件忙"?我无法确切地说出来.

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

jay*_*ngh 110

此错误表示某些其他进程或用户正在访问您的文件.使用lsof检查什么其他进程正在使用它.kill如果需要,您可以使用命令将其终止.

  • 具体的"文本文件忙"错误是关于尝试在执行时修改可执行文件.这里的"文本"指的是正在修改的文件是正在运行的程序的[文本段](http://en.wikipedia.org/wiki/Code_segment).这是一个非常特殊的情况,而不是你的答案似乎暗示的通用情况.即便如此,你的答案并非完全错误. (107认同)
  • 评论的答案似乎已经完成. (4认同)
  • @FelipeValdes 这个名字是半个世纪前的术语历史。例如,在多语言中,程序的文本段与链接段不同,甚至更早的人们谈论二进制文本。/sf/answers/89777831/ (4认同)

Jon*_*ler 29

自从我看到这条消息以来已经有一段时间了,但过去几十年前,它已经在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
Run Code Online (Sandbox Code Playgroud)

因此,为了避免"文本文件忙"的问题,构建创建了一个新文件rmk1,然后将旧文件移动rmkrmk2(重命名不是问题;取消链接),然后将新构建的文件移动rmk1rmk.

我在相当长一段时间内没有看到现代系统上的错误......但我并不是所有经常都有程序重建的人.

  • 这是一个超级快速重现器:`echo -e'#include <unistd.h> \nint main(void){sleep(5); return 0;}'> slowprog.c && cc slowprog.c && cp a.out b .out &&(./a.out&); 睡1 && cp b.out a.out`.在我新的Fedora上生成错误消息"cp:无法创建常规文件'a.out':文本文件忙". (3认同)
  • 当然,这个答案是正确的,获得+1.您可能希望删除"已有一段时间"的免责声明. (3认同)

Mes*_*ssa 12

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

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


小智 5

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

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

bash文件.sh


Cir*_*四事件 5

最小的可运行C POSIX复制示例

我建议您了解底层API,以更好地了解发生了什么。

睡眠

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    sleep(10000);
}
Run Code Online (Sandbox Code Playgroud)

#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);
}
Run Code Online (Sandbox Code Playgroud)

编译并运行:

gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out 
Run Code Online (Sandbox Code Playgroud)

busy.out通过断言,并perror输出:

Text file busy
Run Code Online (Sandbox Code Playgroud)

因此我们推断出该消息是在glibc本身中进行硬编码的。

或者:

echo asdf > sleep.out
Run Code Online (Sandbox Code Playgroud)

使Bash输出:

-bash: sleep.out: Text file busy
Run Code Online (Sandbox Code Playgroud)

对于更复杂的应用程序,您还可以使用strace以下命令进行观察:

strace ./busy.out
Run Code Online (Sandbox Code Playgroud)

其中包含:

openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Run Code Online (Sandbox Code Playgroud)

在Ubuntu 18.04和Linux内核4.15.0上进行了测试。

如果您unlink先出现错误,则不会发生

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);
}
Run Code Online (Sandbox Code Playgroud)

然后类似于上述内容进行编译和运行,这些断言就会通过。

这就解释了为什么它适用于某些程序而不适用于其他程序。例如,如果您这样做:

gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
Run Code Online (Sandbox Code Playgroud)

即使第二个gcc调用正在写入,也不会产生错误sleep.out

快速strace显示GCC首先在写之前取消链接:

 strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
Run Code Online (Sandbox Code Playgroud)

包含:

[pid  3992] unlink("sleep.out")         = 0
[pid  3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
Run Code Online (Sandbox Code Playgroud)

它不会失败的原因是,当您unlink重新写入文件时,它将创建一个新的索引节点,并为正在运行的可执行文件保留一个临时的悬挂索引节点。

但是,如果write没有unlink,它将尝试写入与正在运行的可执行文件相同的受保护inode。

POSIX 7 open()

http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html

[ETXTBSY]

该文件是正在执行的纯过程(共享文本)文件,oflag为O_WRONLY或O_RDWR。

男子2开

ETXTBSY

路径名是指当前正在执行的可执行映像,并且已请求写访问权限。

  • 取消链接情况的基本原理是该文件不再可以从该目录访问,但 inode 仍然存在,并且引用计数 &gt; 0。如果您重新使用该名称,则它是新 inode 中的一个新文件 - 而如果您没有先取消链接,您实际上是在尝试写入受保护的 inode。 (2认同)