Câu trả lời:
Lỗi này có nghĩa là một số quá trình hoặc người dùng khác đang truy cập tệp của bạn. Sử dụng lsof
để kiểm tra những quy trình khác đang sử dụng nó. Bạn có thể sử dụng kill
lệnh để giết nó nếu cần.
Lâu lâu tôi mới thấy tin nhắn đó, nhưng nó đã từng phổ biến trong System V R3 hoặc một vài năm trước đây. Trước đó, điều đó có nghĩa là bạn không thể thay đổi chương trình thực thi trong khi nó đang chạy.
Ví dụ, tôi đang xây dựng một chiếc xe make
được gọi là công việc rmk
, và sau một thời gian nó tự duy trì. Tôi sẽ chạy phiên bản phát triển và để nó xây dựng một phiên bản mới. Để làm cho nó hoạt động, cần phải sử dụng cách giải quyết:
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
Vì vậy, để tránh sự cố với 'tệp văn bản bận', bản dựng đã tạo một tệp mới rmk1
, sau đó chuyển tệp cũ rmk
sang rmk2
(đổi tên không thành vấn đề; hủy liên kết là), rồi chuyển tệp mới được xây dựng rmk1
sangrmk
.
Tôi đã không thấy lỗi trên một hệ thống hiện đại trong một thời gian dài ... nhưng tôi không thường xuyên có các chương trình tự xây dựng lại.
echo -e '#include <unistd.h>\nint main(void){sleep (5);return 0;}' > slowprog.c && cc slowprog.c && cp a.out b.out && (./a.out &) ; sleep 1 && cp b.out a.out
. Đã tạo thông báo lỗi "cp: không thể tạo tệp thông thường 'a.out': Tệp văn bản bận" trên Fedora mới của tôi.
unlink
mặc định sẽ thực hiện theo mặc định.
Điều này xảy ra khi bạn thử và ghi vào một tệp hiện đang được thực thi bởi kernel hoặc thực thi một tệp hiện đang mở để ghi.
Ví dụ sinh sản C POSIX tối thiểu
Tôi khuyên bạn nên hiểu API cơ bản để thấy rõ hơn những gì đang diễn ra.
ngủ
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
bận
#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);
}
Biên dịch và chạy:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
vượt qua các khẳng định và perror
đầu ra:
Text file busy
vì vậy chúng tôi suy luận rằng thông điệp được mã hóa cứng trong chính glibc.
Cách khác:
echo asdf > sleep.out
làm cho đầu ra Bash:
-bash: sleep.out: Text file busy
Đối với một ứng dụng phức tạp hơn, bạn cũng có thể quan sát nó với strace
:
strace ./busy.out
trong đó có:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Đã thử nghiệm trên Ubuntu 18.04, nhân Linux 4.15.0.
Lỗi không xảy ra nếu bạn unlink
lần đầu tiên
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);
}
Sau đó biên dịch và chạy tương tự như trên, và những khẳng định đó vượt qua.
Điều này giải thích tại sao nó hoạt động cho các chương trình nhất định nhưng không phải là chương trình khác. Ví dụ: nếu bạn làm:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
điều đó không tạo ra lỗi, mặc dù gcc
cuộc gọi thứ hai đang ghisleep.out
.
Một cách nhanh chóng strace
cho thấy GCC bỏ liên kết đầu tiên trước khi viết:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
chứa đựng:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
Lý do nó không thất bại là khi bạn unlink
và viết lại tệp, nó tạo ra một nút mới và giữ một nút tạm thời lơ lửng cho tệp thực thi đang chạy.
Nhưng nếu bạn write
không có unlink
, thì nó sẽ cố gắng ghi vào cùng một nút được bảo vệ như đang chạy.
POSIX 7 open()
http://pub.opengroup.org/onlinepub/9699919799/fifts/open.html
[ETXTBSY]
Tệp này là một tệp thủ tục thuần túy (văn bản chia sẻ) đang được thực thi và oflag là O_WRONLY hoặc O_RDWR.
người đàn ông 2 mở
ETXTBSY
tên đường dẫn đề cập đến một hình ảnh thực thi hiện đang được thực thi và yêu cầu truy cập ghi.
unlink
. Linux có bao giờ đọc tệp nhiều hơn một lần sau exec
cuộc gọi đầu tiên không?
Trong trường hợp của tôi, tôi đã cố gắng thực thi một tệp shell (có phần mở rộng .sh) trong môi trường csh và tôi đã nhận được thông báo lỗi đó.
chỉ chạy với bash nó làm việc cho tôi. Ví dụ
bash file.sh
#!/bin/bash
tiêu đề?
#!/usr/bin/csh
hoặc tương đương.
Nếu cố gắng xây dựng phpredis
trên một hộp Linux, bạn có thể cần cho nó thời gian để hoàn thành sửa đổi các quyền của tệp, bằng một sleep
lệnh, trước khi chạy tệp:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmod
sẽ trở lại trước khi quyền được thiết lập. Đó có thể là một vấn đề hệ thống tập tin.
Không biết nguyên nhân nhưng tôi có thể đóng góp một công việc nhanh chóng và dễ dàng.
Tôi vừa trải nghiệm sự kỳ lạ này trên CentOS 6 sau khi "cat> shScript.sh" (dán, ^ Z) sau đó chỉnh sửa tệp trong KWrite. Điều kỳ lạ là không có trường hợp rõ ràng (ps -ef) của việc thực thi tập lệnh.
Công việc nhanh chóng của tôi chỉ đơn giản là "cp shScript.sh shScript2.sh" sau đó tôi có thể thực thi shScript2.sh. Sau đó tôi xóa cả hai. Làm xong!
cat
quá trình. Lần sau sử dụng ^ D, không ^ Z.
Bạn có thể thấy điều này phổ biến hơn trên các chia sẻ mạng CIFS / SMB. Windows không cho phép ghi tệp khi có tệp khác mở tệp đó và ngay cả khi dịch vụ không phải là Windows (có thể là một số sản phẩm NAS khác), nó có thể sẽ tái tạo hành vi tương tự. Có khả năng, nó cũng có thể là một biểu hiện của một số vấn đề NAS tiềm ẩn liên quan đến việc khóa / sao chép.
Nếu bạn đang chạy .sh từ kết nối ssh với một công cụ như MobaXTerm và nếu công cụ đó có tiện ích tự động lưu để chỉnh sửa tệp từ xa từ máy cục bộ, điều đó sẽ khóa tệp.
Đóng và mở lại phiên SSH sẽ giải quyết nó.
Một trong những kinh nghiệm của tôi:
Tôi luôn thay đổi phím tắt mặc định của Chrome thông qua kỹ thuật đảo ngược. Sau khi sửa đổi, tôi quên đóng Chrome và chạy như sau:
sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
Sử dụng strace, bạn có thể tìm thấy nhiều chi tiết hơn:
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)
Tôi đã bắt gặp điều này trong PHP khi sử dụng fopen()
trên một tệp và sau đó thử unlink()
nó trước khi sử dụngfclose()
nó.
Không tốt:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Tốt
$handle = fopen('file.txt');
// do something
fclose($handle);
unlink('file.txt');
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
Text file busy
lỗi trong cụ thể là về việc cố gắng để thay đổi một thực thi trong khi nó đang thực hiện. "Văn bản" ở đây đề cập đến thực tế rằng tệp đang được sửa đổi là phân đoạn văn bản cho một chương trình đang chạy. Đây là một trường hợp rất đặc biệt, và không phải là trường hợp chung chung mà câu trả lời của bạn dường như gợi ý. Mặc dù vậy, câu trả lời của bạn không hoàn toàn không chính xác.