Réponses:
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 kill
commande pour le tuer si nécessaire.
Cela fait un moment que je n'ai pas vu ce message, mais il était répandu dans System V R3 ou à peu près il y a une bonne 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 lancerais la version de développement et lui ferais construire une nouvelle version. Pour le faire fonctionner, 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 déplacé l'ancien rmk
vers rmk2
(renommer n'était pas un problème; dissocier l'était), puis déplacé le nouveau fichier rmk1
vers 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.
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
. Produit le message d'erreur "cp: impossible de créer le fichier régulier 'a.out': Fichier texte occupé" sur mon nouveau Fedora.
unlink
par défaut.
Cela se produit lorsque vous essayez d'écrire dans un fichier en cours d'exécution par le noyau ou que vous exécutez un fichier actuellement ouvert en écriture.
Source: http://wiki.wlug.org.nz/ETXTBSY
Exemple de reproduction minimale C POSIX exécutable
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);
}
Compilez et exécutez:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
transmet les assertions et les perror
sorties:
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 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 d' unlink
abord
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 affirmations sont acceptées.
Cela explique pourquoi cela fonctionne pour certains programmes mais pas pour d'autres. Par exemple, si vous faites:
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 gcc
appel est en cours d'écriture sleep.out
.
Un rapide strace
montre que GCC dissocie d'abord 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 il n'échoue pas est que lorsque vous unlink
réécrivez le fichier, il crée un nouvel inode et conserve un inode suspendu temporaire pour le fichier exécutable en cours d'exécution.
Mais si vous ne le faites write
pas unlink
, alors il essaie d'écrire dans 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é) qui est en cours d'exécution et oflag est O_WRONLY ou O_RDWR.
homme 2 ouvert
ETXTBSY
chemin fait référence à une image exécutable en cours d'exécution et un accès en écriture a été demandé.
unlink
. Linux a-t-il déjà lu le fichier plus d'une fois après le premier exec
appel?
Dans mon cas, j'essayais d'exécuter un fichier shell (avec une extension .sh) dans un environnement csh, et je recevais ce message d'erreur.
courir avec bash ça a marché pour moi. Par exemple
bash fichier.sh
#!/bin/bash
tête?
#!/usr/bin/csh
ou équivalent.
Si vous essayez de construire phpredis
sur une machine Linux, vous devrez peut-être lui laisser le temps de terminer la modification des autorisations de fichier, avec une sleep
commande, avant d'exécuter le fichier:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmod
je reviendrais avant que les autorisations ne soient définies. Cela pourrait être un problème de système de fichiers.
Je ne connais pas la cause mais je peux contribuer à un travail rapide et facile.
Je viens de faire l'expérience de cette bizarrerie sur CentOS 6 après "cat> shScript.sh" (coller, ^ Z) puis en éditant le fichier dans KWrite. Curieusement, il n'y avait aucune instance discernable (ps -ef) du script en cours d'exécution.
Mon travail rapide était simplement de "cp shScript.sh shScript2.sh" puis j'ai pu exécuter shScript2.sh. Ensuite, j'ai supprimé les deux. Terminé!
cat
processus. La prochaine fois, utilisez ^ D, pas ^ Z.
Cela peut être plus courant sur les partages réseau CIFS / SMB. Windows ne permet pas d'écrire un fichier lorsqu'un autre fichier est ouvert, 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, cela pourrait également être une manifestation d'un problème NAS sous-jacent vaguement lié au verrouillage / réplication.
Si vous exécutez le .sh à partir d'une connexion ssh avec un outil comme MobaXTerm, et si ledit outil a un utilitaire d'enregistrement automatique pour éditer le fichier distant à partir de la machine locale, cela verrouille le fichier.
La fermeture et la réouverture de la session SSH le résout.
Une de mes expériences:
Je modifie toujours le raccourci clavier par défaut de Chrome via l'ingénierie inverse. 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)
Je suis tombé sur cela en PHP lors de l'utilisation fopen()
sur un fichier, puis en essayant unlink()
avant de l'utiliser fclose()
.
Pas bien:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Bien:
$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
erreur spécifique consiste à essayer de modifier un exécutable pendant son exécution. Le "Texte" fait ici référence au fait que le fichier en cours de modification est le segment de texte d'un programme en cours d'exécution. Il s'agit d'un cas très particulier, et non du cas générique que semble suggérer votre réponse. Même ainsi, votre réponse n'est pas entièrement incorrecte.