Respostas:
Este erro significa que algum outro processo ou usuário está acessando seu arquivo. Use lsof
para verificar quais outros processos estão usando. Você pode usar o kill
comando para matá-lo, se necessário.
Faz um tempo desde que eu vi essa mensagem, mas costumava prevalecer no System V R3 ou cerca de algumas décadas atrás. Naquela época, isso significava que não era possível alterar um programa executável enquanto ele estava em execução.
Por exemplo, eu estava construindo um make
workalike chamado rmk
, e depois de um tempo ele se manteve. Eu rodaria a versão de desenvolvimento e a compilaria uma nova versão. Para fazê-lo funcionar, era necessário usar a solução 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
Portanto, para evitar problemas com o 'arquivo de texto ocupado', a compilação criou um novo arquivo rmk1
, depois moveu o antigo rmk
para rmk2
(renomear não era um problema; desvincular era) e depois mudou o recém-criado rmk1
para rmk
.
Não vejo o erro em um sistema moderno há um bom tempo ... mas nem sempre os programas são reconstruídos.
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
. Produzi a mensagem de erro "cp: não é possível criar o arquivo regular 'a.out': arquivo de texto ocupado" no meu novo Fedora.
unlink
por padrão.
Isso ocorre quando você tenta gravar em um arquivo que está sendo executado atualmente pelo kernel ou executa um arquivo que está aberto para gravação no momento.
Exemplo mínimo de reprodução executável em C POSIX
Eu recomendo entender a API subjacente para ver melhor o que está acontecendo.
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);
}
Compile e execute:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.out
passa as afirmações e perror
produz:
Text file busy
portanto, deduzimos que a mensagem está codificada na própria glibc.
Alternativamente:
echo asdf > sleep.out
produz saída Bash:
-bash: sleep.out: Text file busy
Para uma aplicação mais complexa, você também pode observá-la com strace
:
strace ./busy.out
que contém:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Testado no Ubuntu 18.04, Linux kernel 4.15.0.
O erro não ocorre se você unlink
primeiro
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);
}
Em seguida, compile e execute analogamente ao acima, e essas afirmações passam.
Isso explica por que funciona em determinados programas, mas não em outros. Por exemplo, se você fizer:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
isso não gera um erro, mesmo que a segunda gcc
chamada esteja sendo gravada sleep.out
.
Uma rápida strace
mostra que o GCC primeiro se desvincula antes de escrever:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
contém:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
O motivo para não falhar é que, quando você unlink
reescreve o arquivo, ele cria um novo inode e mantém um inode temporário pendente para o arquivo executável em execução.
Mas, se você apenas ficar write
sem unlink
, ele tenta gravar no mesmo inode protegido que o executável em execução.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
O arquivo é um arquivo de procedimento puro (texto compartilhado) que está sendo executado e oflag é O_WRONLY ou O_RDWR.
homem 2 aberto
ETXTBSY
nome do caminho refere-se a uma imagem executável que está sendo executada no momento e o acesso de gravação foi solicitado.
unlink
. O Linux já leu o arquivo mais de uma vez após a primeira exec
chamada?
No meu caso, eu estava tentando executar um arquivo shell (com uma extensão .sh) em um ambiente csh e estava recebendo essa mensagem de erro.
apenas rodando com bash funcionou para mim. Por exemplo
bash file.sh
#!/bin/bash
cabeçalho?
#!/usr/bin/csh
ou equivalente.
Se estiver tentando construir phpredis
em uma caixa do Linux, talvez seja necessário tempo para concluir a modificação das permissões do arquivo, com um sleep
comando, antes de executar o arquivo:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmod
que retornaria antes que as permissões fossem definidas. Isso pode ser um problema do sistema de arquivos.
Não sei a causa, mas posso contribuir com uma solução rápida e fácil.
Acabei de experimentar essa essa estranheza no CentOS 6 depois de "cat> shScript.sh" (colar, ^ Z) e depois editar o arquivo no KWrite. Estranhamente, não havia instância discernível (ps -ef) do script em execução.
Meu trabalho rápido foi simplesmente "cp shScript.sh shScript2.sh", depois pude executar o shScript2.sh. Então eu apaguei os dois. Feito!
cat
processo. Da próxima vez, use ^ D, não ^ Z.
Você pode achar que isso é mais comum em compartilhamentos de rede CIFS / SMB. O Windows não permite que um arquivo seja gravado quando algo mais o abrir, e mesmo que o serviço não seja o Windows (pode ser outro produto NAS), provavelmente reproduzirá o mesmo comportamento. Potencialmente, também pode ser uma manifestação de algum problema subjacente do NAS vagamente relacionado ao bloqueio / replicação.
Se você estiver executando o .sh de uma conexão ssh com uma ferramenta como MobaXTerm, e se a ferramenta possuir um utilitário de gravação automática para editar arquivos remotos da máquina local, isso bloqueará o arquivo.
Fechar e reabrir a sessão SSH a resolve.
Uma das minhas experiências:
Sempre altero o atalho de teclado padrão do Chrome por meio de engenharia reversa. Após a modificação, esqueci de fechar o Chrome e executei o seguinte:
sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
Usando strace, você pode encontrar mais detalhes:
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)
Me deparei com isso no PHP ao usar fopen()
um arquivo e depois tentar unlink()
antes de usarfclose()
-lo.
Nada de bom:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Boa:
$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
erro específico é tentar modificar um executável enquanto está em execução. O "Texto" aqui refere-se ao fato de que o arquivo que está sendo modificado é o segmento de texto para um programa em execução. Este é um caso muito especial, e não o genérico que sua resposta parece sugerir. Mesmo assim, sua resposta não está totalmente incorreta.