Antworten:
Dieser Fehler bedeutet, dass ein anderer Prozess oder Benutzer auf Ihre Datei zugreift. Verwenden Sie lsof
diese Option , um zu überprüfen, welche anderen Prozesse es verwenden. Sie können den kill
Befehl verwenden, um ihn bei Bedarf zu beenden.
Es ist schon eine Weile her, dass ich diese Nachricht gesehen habe, aber sie war vor gut ein paar Jahrzehnten in System V R3 oder so weit verbreitet. Damals bedeutete dies, dass Sie eine ausführbare Programmdatei während der Ausführung nicht ändern konnten.
Zum Beispiel baute ich ein make
Workalike namens rmk
, und nach einer Weile war es selbsterhaltend. Ich würde die Entwicklungsversion ausführen und eine neue Version erstellen lassen. Um es zum Laufen zu bringen, musste die Problemumgehung verwendet werden:
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
Um Probleme mit der 'Textdatei beschäftigt' zu vermeiden, erstellte der Build eine neue Datei rmk1
, verschob dann die alte rmk
in rmk2
(Umbenennen war kein Problem; Verknüpfung aufheben war) und verschob die neu erstellte rmk1
in rmk
.
Ich habe den Fehler auf einem modernen System schon eine ganze Weile nicht mehr gesehen ... aber ich habe nicht allzu oft Programme, die sich selbst neu erstellen.
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
. Auf meinem neuen Fedora wurde die Fehlermeldung "cp: Es kann keine reguläre Datei 'a.out': Textdatei beschäftigt" erstellt.
unlink
standardmäßig zuerst geschieht .
Dies tritt auf, wenn Sie versuchen, in eine Datei zu schreiben, die gerade vom Kernel ausgeführt wird, oder wenn Sie eine Datei ausführen, die derzeit zum Schreiben geöffnet ist.
Quelle: http://wiki.wlug.org.nz/ETXTBSY
Beispiel für eine minimal ausführbare C POSIX-Reproduktion
Ich empfehle, die zugrunde liegende API zu verstehen, um besser sehen zu können, was los ist.
sleep.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
beschäftigt.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);
}
Kompilieren und ausführen:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
Übergibt die Asserts und perror
gibt Folgendes aus:
Text file busy
Daraus schließen wir, dass die Nachricht in glibc selbst fest codiert ist.
Alternative:
echo asdf > sleep.out
macht Bash-Ausgabe:
-bash: sleep.out: Text file busy
Für eine komplexere Anwendung können Sie sie auch beobachten mit strace
:
strace ./busy.out
was beinhaltet:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Getestet unter Ubuntu 18.04, Linux Kernel 4.15.0.
Der Fehler tritt nicht auf, wenn Sie unlink
zuerst
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);
}
Dann kompilieren und analog zu den oben genannten ausführen, und diese Behauptungen bestehen.
Dies erklärt, warum es für bestimmte Programme funktioniert, für andere jedoch nicht. ZB wenn Sie tun:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
Das erzeugt keinen Fehler, obwohl der zweite gcc
Aufruf an schreibt sleep.out
.
Eine strace
kurze Darstellung zeigt, dass GCC vor dem Schreiben zuerst die Verknüpfung aufhebt:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
enthält:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
Der Grund, warum dies nicht fehlschlägt, besteht darin, dass beim unlink
erneuten Schreiben der Datei ein neuer Inode erstellt wird und ein temporärer baumelnder Inode für die ausgeführte ausführbare Datei beibehalten wird.
Wenn Sie jedoch nur write
ohne sind unlink
, wird versucht, in denselben geschützten Inode wie die laufende ausführbare Datei zu schreiben.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
Die Datei ist eine reine Prozedurdatei (gemeinsam genutzter Text), die ausgeführt wird, und oflag ist O_WRONLY oder O_RDWR.
Mann 2 offen
ETXTBSY
Pfadname bezieht sich auf ein ausführbares Image, das gerade ausgeführt wird und Schreibzugriff angefordert wurde.
unlink
. Liest Linux die Datei nach dem ersten exec
Aufruf mehr als einmal ?
In meinem Fall habe ich versucht, eine Shell-Datei (mit der Erweiterung .sh) in einer csh-Umgebung auszuführen, und diese Fehlermeldung wurde angezeigt.
Nur mit Bash zu laufen, hat bei mir funktioniert. Beispielsweise
bash file.sh
#!/bin/bash
Header?
#!/usr/bin/csh
oder gleichwertig versuchen .
Wenn Sie versuchen, phpredis
auf einer Linux-Box aufzubauen, müssen Sie ihr möglicherweise Zeit geben, um die Dateiberechtigungen mit einem sleep
Befehl zu ändern, bevor Sie die Datei ausführen:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmod
würde, bevor die Berechtigungen festgelegt wurden. Dies könnte ein Problem mit dem Dateisystem sein.
Ich kenne die Ursache nicht, aber ich kann schnell und einfach Abhilfe schaffen.
Ich habe diese Seltsamkeit unter CentOS 6 gerade erlebt, nachdem "cat> shScript.sh" (Einfügen, ^ Z) und dann die Datei in KWrite bearbeitet wurden. Seltsamerweise war keine Instanz (ps -ef) des ausgeführten Skripts erkennbar.
Meine schnelle Lösung bestand einfach darin, "cp shScript.sh shScript2.sh" zu verwenden, dann konnte ich shScript2.sh ausführen. Dann habe ich beide gelöscht. Getan!
cat
haben. Verwenden Sie das nächste Mal ^ D, nicht ^ Z.
Möglicherweise ist dies bei CIFS / SMB-Netzwerkfreigaben häufiger der Fall. Windows erlaubt nicht, dass eine Datei geschrieben wird, wenn diese Datei in einer anderen Datei geöffnet ist, und selbst wenn der Dienst nicht Windows ist (es kann sich um ein anderes NAS-Produkt handeln), wird wahrscheinlich dasselbe Verhalten reproduziert. Möglicherweise ist dies auch eine Manifestation eines zugrunde liegenden NAS-Problems, das vage mit dem Sperren / Replizieren zusammenhängt.
Wenn Sie die .sh-Datei über eine SSH-Verbindung mit einem Tool wie MobaXTerm ausführen und dieses Tool über ein Dienstprogramm zum automatischen Speichern zum Bearbeiten der Remote-Datei vom lokalen Computer verfügt, wird die Datei gesperrt.
Das Schließen und erneute Öffnen der SSH-Sitzung löst das Problem.
Eine meiner Erfahrungen:
Ich ändere immer die Standardtastenkürzel von Chrome durch Reverse Engineering. Nach der Änderung habe ich vergessen, Chrome zu schließen, und Folgendes ausgeführt:
sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
Mit strace finden Sie weitere Details:
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)
Ich bin in PHP darauf gestoßen, als ich fopen()
eine Datei verwendet habe und es dann versucht habe, unlink()
bevor ich sie verwendet fclose()
habe.
Nicht gut:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Gut:
$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
Fehler handelt es sich insbesondere um den Versuch, eine ausführbare Datei während der Ausführung zu ändern. Der "Text" bezieht sich hier auf die Tatsache, dass die zu ändernde Datei das Textsegment für ein laufendes Programm ist. Dies ist ein ganz besonderer Fall und nicht der generische, den Ihre Antwort zu suggerieren scheint. Trotzdem ist Ihre Antwort nicht ganz falsch.