Wat genereert het bericht “tekstbestand bezet” in Unix?

Welke bewerking genereert de fout “tekstbestand bezet”? Ik kan het niet precies zeggen.

Ik denk dat het te maken heeft met het feit dat ik een tijdelijk python-script aan het maken ben (met tempfile) en execl ervan gebruik, maar ik denk dat execl het bestand dat wordt uitgevoerd verandert.


Antwoord 1, autoriteit 100%

Deze fout betekent dat u een uitvoerbaar bestand probeert te wijzigen terwijl het wordt uitgevoerd. De “Tekst” verwijst hier naar het feit dat het bestand dat wordt gewijzigd het tekstsegment is voor een draaiend programma. Gebruik lsofom te controleren welke andere processen het gebruiken. U kunt het commando killgebruiken om het indien nodig te doden.


Antwoord 2, autoriteit 18%

Het is een tijdje geleden dat ik dat bericht heb gezien, maar het kwam een ​​paar decennia geleden veel voor in System V R3 of daaromtrent. Destijds betekende dit dat je een uitvoerbaar programma niet kon wijzigen terwijl het actief was.

Ik bouwde bijvoorbeeld een makeworkalike genaamd rmk, en na een tijdje was het zelfonderhoudend. Ik zou de ontwikkelversie draaien en een nieuwe versie laten bouwen. Om het werkend te krijgen, was het nodig om de tijdelijke oplossing te gebruiken:

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

Dus om problemen met het ‘tekstbestand bezet’ te voorkomen, heeft de build een nieuw bestand rmk1gemaakt en vervolgens de oude rmkverplaatst naar rmk2(hernoemen was geen probleem; ontkoppelen wel), en verplaatste vervolgens de nieuw gebouwde rmk1naar rmk.

Ik heb de fout al een tijdje niet meer gezien op een modern systeem… maar ik heb niet zo vaak programma’s die zichzelf opnieuw opbouwen.


Antwoord 3, autoriteit 14%

Dit gebeurt wanneer u probeert te schrijven naar een bestand dat momenteel door de kernel wordt uitgevoerd, of wanneer u een bestand uitvoert dat momenteel open staat voor schrijven.

Bron: http://wiki.wlug.org.nz/ETXTBSY


Antwoord 4, autoriteit 8%

Minimaal uitvoerbaar C POSIX-reproductievoorbeeld

Ik raad aan om de onderliggende API te begrijpen om beter te zien wat er aan de hand is.

slaap.c

#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
    sleep(10000);
}

bezet.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);
}

Compileren en uitvoeren:

gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out 

busy.outgeeft de beweringen door, en perrorgeeft:

Text file busy

dus leiden we af dat het bericht hardcoded is in glibc zelf.

Alternatief:

echo asdf > sleep.out

maakt Bash-uitvoer:

-bash: sleep.out: Text file busy

Voor een complexere toepassing kunt u deze ook observeren met strace:

strace ./busy.out

die bevat:

openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)

Getest op Ubuntu 18.04, Linux-kernel 4.15.0.

De fout treedt niet op als u eerst 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);
}

Vervolgens compileren en uitvoeren analoog aan het bovenstaande, en die beweringen slagen.

Dit verklaart waarom het voor bepaalde programma’s wel werkt, maar niet voor andere. bijv. als je dat doet:

gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c

die geen fout genereert, ook al schrijft de tweede gcc-aanroep naar sleep.out.

Een snelle stracelaat zien dat GCC eerst ontkoppelt voordat het schrijft:

strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out

bevat:

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

De reden dat het niet mislukt, is dat wanneer je unlinken het bestand opnieuw schrijft, het een nieuwe inode aanmaakt en een tijdelijke bungelende inode behoudt voor het actieve uitvoerbare bestand.

Maar als je gewoon writezonder unlink, dan probeert het naar dezelfde beveiligde inode te schrijven als het actieve uitvoerbare bestand.

POSIX 7 open()

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

[ETXTBSY]

Het bestand is een puur procedurebestand (gedeelde tekst) dat wordt uitgevoerd en de oflag is O_WRONLY of O_RDWR.

man 2 open

ETXTBSY

padnaam verwijst naar een uitvoerbare afbeelding die momenteel wordt uitgevoerd en waarvoor schrijftoegang is aangevraagd.

glibc-bron

Een snelle grep op 2.30 geeft:

sysdeps/gnu/errlist.c:299:    [ERR_REMAP (ETXTBSY)] = N_("Text file busy"),
sysdeps/mach/hurd/bits/errno.h:62:  ETXTBSY                        = 0x4000001a,        /* Text file busy */

en een handmatige hit in 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

Antwoord 5, autoriteit 3%

In mijn geval probeerde ik een shellbestand uit te voeren (met de extensie .sh)
in een csh-omgeving, en ik kreeg die foutmelding.

gewoon draaien met bash werkte voor mij.
Bijvoorbeeld

bash-bestand.sh


Antwoord 6, autoriteit 2%

Als je phpredisprobeert te bouwen op een Linux-box, moet je het misschien de tijd geven om de bestandspermissies te wijzigen, met een sleepcommando, voordat je het bestand uitvoert:

chmod a+x /usr/bin/php/scripts/phpize \
  && sleep 1 \
  && /usr/bin/php/scripts/phpize

Antwoord 7, autoriteit 2%

Als je de .sh uitvoert vanaf een ssh-verbinding met een tool zoals MobaXTerm, en als die tool een autosave-hulpprogramma heeft om het externe bestand vanaf de lokale computer te bewerken, zal dat het bestand vergrendelen.

Sluiten en heropenen van de SSH-sessie lost het op.


Antwoord 8

Misschien komt dit vaker voor op CIFS/SMB-netwerkshares. Windows staat niet toe dat een bestand wordt geschreven wanneer iets anders dat bestand open heeft staan, en zelfs als de service geen Windows is (het kan een ander NAS-product zijn), zal het waarschijnlijk hetzelfde gedrag reproduceren. Mogelijk is het ook een manifestatie van een onderliggend NAS-probleem dat vaag gerelateerd is aan vergrendeling/replicatie.


Antwoord 9

Een van mijn ervaringen:

Ik wijzig altijd de standaard sneltoets van Chrome via reverse engineering. Na wijziging vergat ik Chrome te sluiten en voerde het volgende uit:

sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy

Met behulp van strace kun je de meer details vinden:

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)

Antwoord 10

Ik weet de oorzaak niet, maar ik kan een snelle en gemakkelijke oplossing bieden.

Ik heb net deze rariteit ervaren op CentOS 6 nadat cat > shScript.sh(plakken, ^Z) en vervolgens het bestand bewerken in KWrite. Vreemd genoeg was er geen waarneembare instantie (ps -ef) van het script dat werd uitgevoerd.

Mijn snelle oplossing was gewoon om cp shScript.sh shScript2.shen vervolgens kon ik shScript2.shuitvoeren. Toen heb ik beide verwijderd. Klaar!


Antwoord 11

Ik kwam dit tegen in PHP toen ik fopen()op een bestand gebruikte en het vervolgens probeerde te unlink()voordat ik fclose()erop.

Niet goed:

$handle = fopen('file.txt');
// do something
unlink('file.txt');

Goed:

$handle = fopen('file.txt');
// do something
fclose($handle);
unlink('file.txt');

Antwoord 12

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

Other episodes