Ответы:
Эта ошибка означает, что к вашему файлу обращается какой-то другой процесс или пользователь. Используйте, lsofчтобы проверить, какие другие процессы его используют. При необходимости вы можете использовать killкоманду, чтобы убить его.
Я давно не видел этого сообщения, но раньше оно было преобладающим в System V R3 или около того, пару десятилетий назад. Тогда это означало, что вы не могли изменить исполняемый файл программы во время ее работы.
Например, я создавал makeподобную работу под названием rmk, и через некоторое время она стала самоподдерживающейся. Я бы запустил версию для разработки и заставил ее построить новую версию. Чтобы заставить его работать, нужно было использовать обходной путь:
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
Итак, чтобы избежать проблем с «занятым текстовым файлом», сборка создала новый файл rmk1, затем переместила старый rmkв rmk2(переименование не было проблемой; разорвать связь было), а затем переместила вновь созданный файл rmk1в rmk.
Я давно не видел ошибки в современной системе ... но у меня не так уж часто программы перестраиваются сами.
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. Выдало сообщение об ошибке «cp: невозможно создать обычный файл 'a.out': текстовый файл занят» в моей новой Fedora.
unlinkпо умолчанию.
Это происходит, когда вы пытаетесь выполнить запись в файл, который в данный момент выполняется ядром, или выполняете файл, который в данный момент открыт для записи.
Источник: http://wiki.wlug.org.nz/ETXTBSY
Минимальный пример воспроизведения POSIX на C
Я рекомендую разобраться в базовом API, чтобы лучше понять, что происходит.
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);
}
Скомпилируйте и запустите:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.outпередает утверждения и perrorвыводит:
Text file busy
Таким образом, мы делаем вывод, что сообщение жестко закодировано в самой glibc.
В качестве альтернативы:
echo asdf > sleep.out
выводит Bash:
-bash: sleep.out: Text file busy
Для более сложных приложений вы также можете наблюдать это с помощью strace:
strace ./busy.out
который содержит:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Проверено на Ubuntu 18.04, ядро Linux 4.15.0.
Ошибка не возникает, если вы 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);
}
Затем скомпилируйте и запустите аналогично предыдущему, и эти утверждения пройдут.
Это объясняет, почему он работает с некоторыми программами, но не работает с другими. Например, если вы это сделаете:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
это не вызывает ошибки, даже если второй gccвызов выполняет запись sleep.out.
Быстро straceпоказывает, что GCC сначала отключается перед записью:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
содержит:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
Причина, по которой он не терпит неудачу, заключается в том, что когда вы unlinkи перезаписываете файл, он создает новый индексный дескриптор и сохраняет временный висячий индексный дескриптор для запущенного исполняемого файла.
Но если у вас просто writeнет unlink, тогда он пытается записать в тот же защищенный индекс, что и запущенный исполняемый файл.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
Файл представляет собой файл чистой процедуры (общий текст), который выполняется и имеет значение O_WRONLY или O_RDWR.
человек 2 открытый
ETXTBSY
pathname относится к исполняемому образу, который в настоящее время выполняется, и был запрошен доступ на запись.
unlink. Считывает ли Linux когда-либо файл более одного раза после первого execвызова?
В моем случае я пытался запустить файл оболочки (с расширением .sh) в среде csh и получал это сообщение об ошибке.
просто работая с bash, это сработало для меня. Например
Bash file.sh
#!/bin/bashзаголовок?
#!/usr/bin/cshили аналог.
Если вы пытаетесь создать систему phpredisна Linux, вам может потребоваться время, чтобы завершить изменение прав доступа к файлу с помощью sleepкоманды, прежде чем запускать файл:
chmod a+x /usr/bin/php/scripts/phpize \
&& sleep 1 \
&& /usr/bin/php/scripts/phpize
chmodчто вернусь до того, как будут установлены разрешения. Это может быть проблема с файловой системой.
Не знаю причины, но я могу помочь быстро и легко решить эту проблему.
Я только что испытал эту странность в CentOS 6 после "cat> shScript.sh" (вставить, ^ Z), а затем отредактировав файл в KWrite. Как ни странно, не было заметного экземпляра (ps -ef) выполнения скрипта.
Моей быстрой работой было просто "cp shScript.sh shScript2.sh", после чего я смог запустить shScript2.sh. Потом удалил оба. Готово!
catпроцесс. В следующий раз используйте ^ D, а не ^ Z.
Вы можете обнаружить, что это чаще встречается в общих сетевых папках CIFS / SMB. Windows не позволяет записывать файл, когда этот файл открыт чем-то другим, и даже если это служба, отличная от Windows (это может быть другой продукт NAS), она, скорее всего, будет воспроизводить то же поведение. Потенциально это также может быть проявлением некоторой основной проблемы NAS, нечетко связанной с блокировкой / репликацией.
Если вы запускаете .sh из ssh-соединения с помощью такого инструмента, как MobaXTerm, и если в указанном инструменте есть утилита автосохранения для редактирования удаленного файла с локального компьютера, это заблокирует файл.
Ее решает закрытие и повторное открытие сеанса SSH.
Один из моих опытов:
Я всегда меняю сочетание клавиш по умолчанию в Chrome с помощью обратного проектирования. После модификации я забыл закрыть Chrome и выполнил следующее:
sudo cp chrome /opt/google/chrome/chrome
cp: cannot create regular file '/opt/google/chrome/chrome': Text file busy
Используя strace, вы можете найти более подробную информацию:
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)
Я столкнулся с этим в PHP при использовании fopen()в файле, а затем пытался сделать unlink()это перед использованием fclose()в нем.
Не хорошо:
$handle = fopen('file.txt');
// do something
unlink('file.txt');
Хорошо:
$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ошибка связана с попыткой изменить исполняемый файл во время его выполнения. «Текст» здесь относится к тому факту, что изменяемый файл является текстовым сегментом для запущенной программы. Это очень частный случай, а не тот общий, который, кажется, предполагает ваш ответ. Тем не менее, ваш ответ не совсем неверен.