Quelle opération génère l'erreur "fichier texte occupé"? Je suis incapable de dire exactement.
Je pense que cela est lié au fait que je crée un script python temporaire (en utilisant tempfile) et en utilisant execl, mais je pense que execl modifie le fichier en cours d'exécution.
Cette erreur signifie qu'un autre processus ou utilisateur accède à votre fichier. Utilisez lsof
pour vérifier quels autres processus l'utilisent. Vous pouvez utiliser la commande kill
pour le tuer si nécessaire.
Cela fait longtemps que je n'ai pas vu ce message, mais il prévalait dans le système V R3 ou il y a une vingtaine d'années. À l'époque, cela signifiait que vous ne pouviez pas modifier un exécutable de programme pendant son exécution.
Par exemple, je construisais un make
workalike appelé rmk
et après un certain temps, il s'est auto-entretenu. Je voudrais exécuter la version de développement et le faire construire une nouvelle version. Pour que cela fonctionne, il était nécessaire d'utiliser la solution de contournement:
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
Ainsi, pour éviter les problèmes avec le «fichier texte occupé», la construction a créé un nouveau fichier rmk1
, puis a déplacé l'ancien rmk
à rmk2
(renommer ne posait pas de problème; unlink était), puis a déplacé le rmk1
nouvellement créé à rmk
.
Je n'ai pas vu l'erreur sur un système moderne depuis un bon moment ... mais je n'ai pas souvent des programmes qui se reconstruisent.
Cela se produit lorsque vous essayez d'écrire dans un fichier en cours d'exécution par le noyau ou d'exécuter un fichier en cours d'écriture.
Source: http://wiki.wlug.org.nz/ETXTBSY
Dans mon cas, j’essayais d’exécuter un fichier Shell (avec une extension .sh) Dans un environnement csh et j’obtenais ce message d’erreur.
juste courir avec bash cela a fonctionné pour moi . Par exemple
bash fichier.sh
Vous constaterez peut-être que cela est plus courant sur les partages réseau CIFS/SMB. Windows n'autorise pas l'écriture d'un fichier lorsque quelque chose d'autre l'ouvre, et même si le service n'est pas Windows (il peut s'agir d'un autre produit NAS), il reproduira probablement le même comportement. Potentiellement, il pourrait également s'agir d'une manifestation d'un problème sous-jacent NAS lié vaguement au verrouillage/à la réplication.
Si vous essayez de construire phpredis
sur une machine Linux, vous devrez peut-être lui donner le temps de modifier les autorisations de fichiers à l'aide d'une commande sleep
avant d'exécuter le fichier:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
Je ne connais pas la cause, mais je peux contribuer rapidement et facilement au travail.
Je viens de faire l'expérience de cette bizarrerie sur CentOS 6 après "cat> shScript.sh" (coller, ^ Z), puis l'édition du fichier dans KWrite. Curieusement, il n'y avait pas d'instance discernable (ps -ef) du script en cours d'exécution.
Mon travail rapide consistait simplement à "cp shScript.sh shScript2.sh", puis j'ai pu exécuter shScript2.sh. Puis j'ai supprimé les deux. Terminé!
Une de mes expériences:
Je change toujours le raccourci clavier par défaut de Chrome via le reverse engineering. Après modification, j'ai oublié de fermer Chrome et j'ai exécuté ce qui suit:
Sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
En utilisant strace, vous pouvez trouver plus de détails:
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)
Minimal exécutable C Exemple de reproduction POSIX
Je recommande de comprendre l'API sous-jacente pour mieux voir ce qui se passe.
sommeil.c:
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
occupé.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);
}
Compiler et exécuter:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
passe les assertions et perror
génère:
Text file busy
nous en déduisons donc que le message est codé en dur dans la glibc elle-même.
Alternativement:
echo asdf > sleep.out
rend la sortie de Bash:
-bash: sleep.out: Text file busy
Pour une application plus complexe, vous pouvez également l'observer avec strace
:
strace ./busy.out
qui contient:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Testé sur Ubuntu 18.04, noyau Linux 4.15.0.
L'erreur ne se produit pas si vous unlink
premier
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);
}
Ensuite, compilez et exécutez de manière analogue à ce qui précède, et ces assertions passent.
Cela explique pourquoi cela fonctionne pour certains programmes mais pas pour d’autres. Par exemple. si tu fais:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
cela ne génère pas d'erreur, même si le deuxième appel gcc
écrit dans sleep.out
.
Une rapide strace
montre que GCC dissocie d'abord les liens avant d'écrire:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
contient:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
La raison pour laquelle cela n'échoue pas, c'est que lorsque vous unlink
et ré-écrivez le fichier, il crée un nouvel inode et conserve un inode temporaire pour le fichier exécutable en cours d'exécution.
Mais si vous ne faites que write
sans unlink
, il essaiera d'écrire sur le même inode protégé que l'exécutable en cours d'exécution.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
Le fichier est un fichier de procédure pure (texte partagé) en cours d'exécution et oflag est O_WRONLY ou O_RDWR.
man 2 ouvert
ETXTBSY
pathname fait référence à une image exécutable en cours d'exécution et un accès en écriture a été demandé.
Si vous exécutez le fichier .sh à partir d'une connexion ssh avec un outil tel que MobaXTerm et que cet outil dispose d'un utilitaire d'enregistrement automatique permettant de modifier un fichier distant à partir d'une machine locale, le fichier sera verrouillé.
Fermer et rouvrir la session SSH le résout.
Je suis tombé sur cette information dans PHP en utilisant fopen()
sur un fichier, puis en essayant de le unlink()
avant d'utiliser fclose()
dessus.
Pas bien:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Bien:
$handle = fopen('file.txt');
// do something
fclose($handle);
unlink('file.txt');