การดำเนินการใดทำให้เกิดข้อผิดพลาด "ไฟล์ข้อความไม่ว่าง" ฉันไม่สามารถบอกได้อย่างแน่ชัด
ฉันคิดว่ามันเกี่ยวข้องกับการที่ฉันสร้างสคริปต์ 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
ไฟล์.
ฉันไม่เห็นข้อผิดพลาดในระบบที่ทันสมัยมาระยะหนึ่งแล้ว ... แต่ฉันก็ไม่ใช่ทั้งหมดที่มักจะสร้างโปรแกรมขึ้นมาใหม่
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
ซุปเปอร์อย่างรวดเร็ว: สร้างข้อความแสดงข้อผิดพลาด "cp: ไม่สามารถสร้างไฟล์ปกติ" a.out ": ไฟล์ข้อความไม่ว่าง" บน Fedora ใหม่ของฉัน
unlink
โดยค่าเริ่มต้น
สิ่งนี้เกิดขึ้นเมื่อคุณพยายามและเขียนไปยังไฟล์ที่กำลังดำเนินการโดยเคอร์เนลหรือเรียกใช้ไฟล์ที่กำลังเปิดอยู่สำหรับการเขียน
ตัวอย่างการสร้าง 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 kernel 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);
}
จากนั้นรวบรวมและเรียกใช้แบบอะนาล็อกกับข้างต้นและคำยืนยันเหล่านั้นก็ผ่าน
สิ่งนี้อธิบายว่าเหตุใดจึงใช้งานได้กับโปรแกรมบางโปรแกรม แต่ใช้ไม่ได้ เช่นถ้าคุณทำ:
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
เขียนไฟล์และเขียนใหม่ไฟล์จะสร้างไอโหนดใหม่และเก็บไอโหนดห้อยไว้ชั่วคราวสำหรับไฟล์ปฏิบัติการที่รันอยู่
แต่ถ้าคุณwrite
ไม่มีunlink
มันก็จะพยายามเขียนไปยังไอโหนดที่ได้รับการป้องกันเช่นเดียวกับปฏิบัติการที่รันอยู่
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
ไฟล์นี้เป็นไฟล์โพรซีเดอร์บริสุทธิ์ (ข้อความที่แบ่งใช้) ที่กำลังดำเนินการและ oflag คือ O_WRONLY หรือ O_RDWR
ชาย 2 เปิด
ETXTBSY
ชื่อพา ธ หมายถึงอิมเมจที่เรียกใช้งานได้ซึ่งกำลังดำเนินการอยู่และร้องขอการเข้าถึงการเขียน
ที่มา glibc
grep อย่างรวดเร็วบน 2.30 ช่วยให้:
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
unlink
ฉันยังสงสัยว่าทำไมตรงกันข้ามไม่ได้ให้ข้อผิดพลาดถ้าคุณพยายามที่จะเขียนได้โดยไม่ต้อง Linux เคยอ่านไฟล์มากกว่าหนึ่งครั้งหลังจากการexec
โทรครั้งแรกหรือไม่?
ในกรณีของฉันฉันพยายามเรียกใช้ไฟล์เชลล์ (ที่มีนามสกุล. sh) ในสภาพแวดล้อม csh และฉันได้รับข้อความแสดงข้อผิดพลาดนั้น
แค่วิ่งไปพร้อมกับทุบตีมันได้ผลสำหรับฉัน ตัวอย่างเช่น
bash file.sh
#!/bin/bash
ส่วนหัวหรือไม่?
#!/usr/bin/csh
หรือเทียบเท่า
หากพยายามสร้างphpredis
บนกล่อง Linux คุณอาจต้องให้เวลาในการแก้ไขการอนุญาตไฟล์ให้เสร็จสมบูรณ์ด้วยsleep
คำสั่งก่อนที่จะเรียกใช้ไฟล์:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmod
จะกลับมาก่อนกำหนดสิทธิ์ นั่นอาจเป็นปัญหาระบบไฟล์
คุณอาจพบว่าสิ่งนี้พบได้บ่อยในการแชร์เครือข่าย CIFS / SMB Windows ไม่อนุญาตให้เขียนไฟล์เมื่อมีไฟล์อื่นเปิดอยู่และแม้ว่าบริการจะไม่ใช่ Windows (อาจเป็นผลิตภัณฑ์ NAS อื่น ๆ ) แต่ก็มีแนวโน้มที่จะสร้างพฤติกรรมเดียวกัน อาจเป็นไปได้ว่าอาจเป็นการแสดงให้เห็นถึงปัญหา NAS พื้นฐานบางอย่างที่เกี่ยวข้องกับการล็อก / การจำลองแบบคลุมเครือ
หากคุณกำลังเรียกใช้. sh จากการเชื่อมต่อ ssh ด้วยเครื่องมือเช่น MobaXTerm และหากเครื่องมือดังกล่าวมียูทิลิตี้บันทึกอัตโนมัติเพื่อแก้ไขไฟล์ระยะไกลจากเครื่องภายในระบบจะล็อกไฟล์
การปิดและเปิดเซสชัน SSH ใหม่จะช่วยแก้ปัญหาได้
ไม่ทราบสาเหตุ แต่ฉันสามารถมีส่วนร่วมในการแก้ไขปัญหาที่ง่ายและรวดเร็ว
ฉันเพิ่งพบความแปลกประหลาดนี้ใน CentOS 6 หลังจากcat > shScript.sh
(วาง^Z
) จากนั้นแก้ไขไฟล์ใน KWrite ผิดปกติไม่มีอินสแตนซ์ ( ps -ef
) ที่มองเห็นได้ของการเรียกใช้สคริปต์
การแก้ไขปัญหาอย่างรวดเร็วของฉันเป็นเพียงแค่cp shScript.sh shScript2.sh
ตอนนั้นฉันก็สามารถดำเนินการshScript2.sh
ได้ จากนั้นฉันก็ลบทั้งสองอย่าง เสร็จแล้ว!
cat
กระบวนการ ใช้ครั้งต่อไป ^ D ไม่ใช่ ^ Z
หนึ่งในประสบการณ์ของฉัน:
ฉันเปลี่ยนแป้นพิมพ์ลัดเริ่มต้นของ 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)
ฉันเจอสิ่งนี้ใน PHP เมื่อใช้fopen()
กับไฟล์แล้วลองunlink()
ใช้ก่อนใช้fclose()
มัน
ไม่ดี:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
ดี:
$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
ผิดพลาดในที่เฉพาะเจาะจงเกี่ยวกับการพยายามที่จะปรับเปลี่ยนปฏิบัติการในขณะที่มีการดำเนินการ "ข้อความ" ในที่นี้หมายถึงความจริงที่ว่าไฟล์ที่กำลังแก้ไขคือส่วนข้อความสำหรับโปรแกรมที่กำลังทำงานอยู่ นี่เป็นกรณีพิเศษมากไม่ใช่กรณีทั่วไปที่ดูเหมือนว่าคำตอบของคุณจะแนะนำ ถึงกระนั้นคำตอบของคุณก็ไม่ถูกต้องทั้งหมด