什么操作生成错误"文本文件忙"?我无法确切地说出来.
我认为这与我正在创建一个临时python脚本(使用tempfile)并使用它的execl有关,但我认为execl会更改正在运行的文件.
jay*_*ngh 110
此错误表示某些其他进程或用户正在访问您的文件.使用lsof检查什么其他进程正在使用它.kill如果需要,您可以使用命令将其终止.
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,然后将旧文件移动rmk到rmk2(重命名不是问题;取消链接),然后将新构建的文件移动rmk1到rmk.
我在相当长一段时间内没有看到现代系统上的错误......但我并不是所有经常都有程序重建的人.
最小的可运行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
路径名是指当前正在执行的可执行映像,并且已请求写访问权限。