Risposte:
Questo errore indica che un altro processo o utente sta accedendo al tuo file. Utilizzare lsof
per verificare quali altri processi lo stanno utilizzando. Puoi usare il kill
comando per ucciderlo se necessario.
È da un po 'che non vedo quel messaggio, ma era prevalente in System V R3 o giù di lì un bel paio di decenni fa. Allora, significava che non era possibile modificare un eseguibile del programma mentre era in esecuzione.
Ad esempio, stavo costruendo un make
workalike chiamato rmk
, e dopo un po 'si auto-manteneva. Avrei eseguito la versione di sviluppo e l'avrei costruita una nuova versione. Per farlo funzionare, era necessario utilizzare la soluzione alternativa:
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
Quindi, per evitare problemi con il "file di testo occupato", la build ha creato un nuovo file rmk1
, quindi ha spostato il vecchio rmk
in rmk2
(rinominare non era un problema; unlink era) e quindi spostato il nuovo costruito rmk1
in rmk
.
Non vedo l'errore su un sistema moderno da un po 'di tempo ... ma non ho spesso programmi che si ricostruiscono da soli.
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
. Ha prodotto il messaggio di errore "cp: impossibile creare il file regolare 'a.out': file di testo occupato" sul mio Fedora nuovo.
unlink
per impostazione predefinita.
Ciò si verifica quando si tenta di scrivere su un file che è attualmente in esecuzione dal kernel o si esegue un file che è attualmente aperto per la scrittura.
Esempio di riproduzione POSIX C eseguibile minima
Consiglio di comprendere l'API sottostante per vedere meglio cosa sta succedendo.
sleep.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
busy.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);
}
Compila ed esegui:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
passa le affermazioni e perror
produce:
Text file busy
quindi deduciamo che il messaggio è hardcoded nello stesso glibc.
In alternativa:
echo asdf > sleep.out
rende l'uscita Bash:
-bash: sleep.out: Text file busy
Per un'applicazione più complessa, puoi anche osservarla con strace
:
strace ./busy.out
che contiene:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Testato su Ubuntu 18.04, kernel Linux 4.15.0.
L'errore non si verifica se unlink
prima
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);
}
Quindi compilare ed eseguire in modo analogo a quanto sopra, e tali affermazioni passano.
Questo spiega perché funziona per determinati programmi ma non per altri. Ad esempio se lo fai:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
che non genera un errore, anche se la seconda gcc
chiamata sta scrivendo sleep.out
.
Un rapido strace
mostra che GCC prima scollega prima di scrivere:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
contiene:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
Il motivo per cui non fallisce è che quando si unlink
riscrive il file, crea un nuovo inode e mantiene un inode temporaneo pendente per il file eseguibile in esecuzione.
Ma se proprio write
senza unlink
, allora prova a scrivere sullo stesso inode protetto dell'eseguibile in esecuzione.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
Il file è un file di procedura pura (testo condiviso) che viene eseguito e oflag è O_WRONLY o O_RDWR.
man 2 open
ETXTBSY
nome percorso si riferisce a un'immagine eseguibile che è attualmente in esecuzione ed è stato richiesto l'accesso in scrittura.
unlink
. Linux ha mai letto il file più di una volta dopo la prima exec
chiamata?
Nel mio caso, stavo cercando di eseguire un file shell (con estensione .sh) in un ambiente csh e stavo ricevendo quel messaggio di errore.
solo correndo con bash ha funzionato per me. Per esempio
bash file.sh
#!/bin/bash
un'intestazione?
#!/usr/bin/csh
o equivalente.
Se phpredis
stai tentando di compilare su un box Linux, potresti dover concedere il tempo necessario per completare la modifica delle autorizzazioni del file, con un sleep
comando, prima di eseguire il file:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmod
che tornerebbe prima che le autorizzazioni fossero impostate. Potrebbe essere un problema con il filesystem.
Non conosco la causa, ma posso contribuire in modo rapido e semplice.
Ho appena sperimentato questa stranezza su CentOS 6 dopo "cat> shScript.sh" (incolla, ^ Z), quindi modificando il file in KWrite. Stranamente non c'era un'istanza riconoscibile (ps -ef) dell'esecuzione dello script.
Il mio rapido lavoro era semplicemente "cp shScript.sh shScript2.sh", quindi sono stato in grado di eseguire shScript2.sh. Quindi ho eliminato entrambi. Fatto!
cat
processo. La prossima volta usa ^ D, non ^ Z.
È possibile che questo sia più comune nelle condivisioni di rete CIFS / SMB. Windows non consente la scrittura di un file quando qualcos'altro ha quel file aperto e anche se il servizio non è Windows (potrebbe essere un altro prodotto NAS), probabilmente riprodurrà lo stesso comportamento. Potenzialmente, potrebbe anche essere una manifestazione di alcuni problemi NAS sottostanti vagamente correlati al blocco / replica.
Se stai eseguendo il .sh da una connessione ssh con uno strumento come MobaXTerm, e se detto strumento ha un'utilità di salvataggio automatico per modificare il file remoto dal computer locale, questo bloccherà il file.
La chiusura e la riapertura della sessione SSH la risolvono.
Una mia esperienza:
Cambio sempre la scorciatoia da tastiera predefinita di Chrome tramite il reverse engineering. Dopo la modifica, ho dimenticato di chiudere Chrome ed ho eseguito quanto segue:
sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
Usando strace, puoi trovare maggiori dettagli:
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)
Mi sono imbattuto in PHP quando ho usato fopen()
un file e poi ci unlink()
ho provato prima di usarlo fclose()
.
Non buono:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Buona:
$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
errore in particolare riguarda il tentativo di modificare un eseguibile mentre è in esecuzione. Il "Testo" qui si riferisce al fatto che il file che si sta modificando è il segmento di testo per un programma in esecuzione. Questo è un caso molto speciale, e non quello generico che la tua risposta sembra suggerire. Anche così, la tua risposta non è del tutto errata.