Unixで「テキストファイルビジー」メッセージが生成されるのはなぜですか。


137

「テキストファイルがビジーです」というエラーが発生するのはどのような操作ですか?正確には言えません。

私は一時的なpythonスクリプトを(tempfileを使用して)作成し、そこからexeclを使用しているという事実に関連していると思いますが、execlは実行中のファイルを変更すると思います。

回答:


130

このエラーは、他のプロセスまたはユーザーがファイルにアクセスしていることを意味します。lsof他のプロセスがそれを使用しているものを確認するために使用します。kill必要に応じて、コマンドを使用して強制終了できます。


115
Text file busy特定の誤差は、それが実行中に実行可能ファイルを変更しようとしている程度です。ここで「テキスト」とは、変更されるファイルが実行中のプログラムのテキストセグメントであることを意味します。これは非常に特殊なケースであり、回答が示唆する一般的なケースではありません。それでも、あなたの答えは完全に間違っているわけではありません。
ArjunShankar 2014年

4
コメント付きの回答は完全なようです。
Penz

OPは、エラーの意味を説明するためではなく、エラーを生成する操作を尋ねました。
WonderWorker 2017

unixがファイルを「テキストファイル」であると想定しているという事実は論理的ではないと思います。私の場合、このエラーを引き起こしたのはバイナリファイルでした。
フェリペバルデス

1
@FelipeValdesこの名前は、半世紀前の用語から歴史的なものです。たとえば、multicsでは、プログラムのテキストセグメントはリンクセグメントとは異なり、以前の人でもバイナリテキストについて話していました。stackoverflow.com/a/1282540/833300
jma 2018年

30

私がそのメッセージを見たのは久しぶりですが、以前は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、古いファイルをに移動rmkrmk2(名前の変更は問題ではありませんでした。リンクの解除は問題ではありませんでした)、新しくビルドしたファイルをに移動しましrmk1rmk

私は最近のシステムでエラーをかなり長い間見ていません...しかし、プログラム自体が再構築されることはあまりありません。


3
これが超迅速な再生器です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。私の新しいFedoraでエラーメッセージ「cp:通常のファイル 'a.out'を作成できません:テキストファイルがビジーです」を生成しました。
ArjunShankar 2014年

3
もちろん、この答えは正しく、+ 1を獲得します。「久しぶり」の免責事項を削除することをお勧めします。
ArjunShankar 2014年

:@ArjunShankarここで「直接」のシステムコールを備えたモダンなLinux上でCの再現であるstackoverflow.com/questions/16764946/...の GCCのみ上書き最初がない場合ので、今日実行可能ファイルを実行することができunlink、デフォルトでは。
Ciro Santilli郝海东冠状病六四事件法轮功

14

これは、現在カーネルによって実行されているファイルに書き込もうとしたり、現在書き込み用に開いているファイルを実行したりすると発生します。

出典:http : //wiki.wlug.org.nz/ETXTBSY


6

最小限の実行可能なC POSIX再現の例

何が起こっているのかをよりよく理解するために、基盤となる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

2番目の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、ファイルを再書き込みすると、新しいiノードが作成され、実行中の実行可能ファイル用に一時的なぶら下がりiノードが保持されるためです。

しかし、がwriteない場合unlink、実行中の実行可能ファイルと同じ保護されたiノードに書き込もうとします。

POSIX 7 open()

http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html

[ETXTBSY]

ファイルは実行中の純粋なプロシージャ(共有テキスト)ファイルで、oflagはO_WRONLYまたはO_RDWRです。

男2オープン

ETXTBSY

pathnameは、現在実行中であり、書き込みアクセスが要求された実行可能イメージを指します。


1
リンク解除の場合の理論的根拠は、ファイルがそのディレクトリからアクセスできなくなったにもかかわらず、iノードがまだrefcount> 0で存在しているということです。名前を再利用すると、新しいiノード内の新しいファイルになります。最初にリンクを解除するのではなく、実際には保護されたiノードに書き込もうとしています。
Penz

コメントのための@ペンズオブリガード、Leandro。逆に、なしで書こうとするとエラーになるのはなぜでしょうかunlink。Linuxは、最初のexec呼び出し後にファイルを2回以上読み取ることはありますか?
Ciro Santilli郝海东冠状病六四事件法轮功

ETXTBSYを生成しているのは、iノード保護です。リンクを解除しないと、書き込みはファイルの実行によって保護されているiノードに送られます。unlinkを使用すると、保護されていない新しいiノードを取得します。(ここでは「保護された」という用語
Penz

5

私の場合、csh環境でシェルファイル(拡張子.sh)を実行しようとしていたところ、そのエラーメッセージが表示されました。

bashで実行するだけでうまくいきました。例えば

bash file.sh


1
それはありました#!/bin/bashヘッダを?
Penz

次のヘッダー#!/ bin / sh
Rafayel Paremuzyan

#!/usr/bin/cshまたは同等のものを使用してみてください。
ペンツ

3

phpredisLinuxボックスでビルドしようとする場合sleep、ファイルを実行する前に、コマンドを使用してファイルのアクセス許可の変更を完了する時間を与える必要がある場合があります。

chmod a+x /usr/bin/php/scripts/phpize \
  && sleep 1 \
  && /usr/bin/php/scripts/phpize

chmod権限が設定される前に戻るとは思いません。ファイルシステムの問題かもしれません。
Penz

これは、ビルドされているDockerイメージ内で発生しました。
ステファン

1
Dockerには複数のストレージドライバーがありますが、それらのすべてが完璧であるとは限りません。
Penz

それでも、Dockerイメージを構築するときにこの問題が発生している人にとっては非常に良いヒントです。
Maciej Gol

2

原因は不明ですが、迅速かつ簡単な回避策を提供できます。

"cat> shScript.sh"(貼り付け、^ Z)を実行し、KWriteでファイルを編集した後、CentOS 6でこの奇妙な問題を経験しました。奇妙なことに、実行中のスクリプトの識別可能なインスタンス(ps -ef)がありませんでした。

私の簡単な回避策は、単に「cp shScript.sh shScript2.sh」を実行することでした。その後、shScript2.shを実行することができました。次に、両方を削除しました。できた!


あなたの問題はあなたがプロセスを中断したためでしたcat。次回は^ Zではなく^ Dを使用してください。
Vladimir Panteleev

かなり正しいウラジミール。ありがとう!これは、DOS / CMDプロンプトで実行したことです。古いハビ... ...以来起こっていない:)
ScottWelker

2

CIFS / SMBネットワーク共有では、これがより一般的である場合があります。Windowsは、何か他のファイルが開かれている場合、ファイルの書き込みを許可していません。サービスがWindowsでない場合でも(他のNAS製品である可能性があります)、同じ動作を再現する可能性があります。潜在的に、ロック/レプリケーションに漠然と関連するいくつかの根本的なNAS問題の兆候である可能性もあります。


2

MobaXTermなどのツールを使用してssh接続から.shを実行していて、そのツールにローカルマシンからリモートファイルを編集するための自動保存ユーティリティがある場合は、ファイルがロックされます。

SSHセッションを閉じて再度開くと解決します。


1

私の経験の1つ:

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)

0

私はfopen()ファイルで使用しているときにPHPでこれに遭遇しunlink()、それを使用する前に試行しfclose()ました。

良くない:

$handle = fopen('file.txt');
// do something
unlink('file.txt');

良い:

$handle = fopen('file.txt');
// do something
fclose($handle);
unlink('file.txt');

Windowsでは私は推測しますか?Linux上のシステムは通常、開いているファイルを削除するために私達を許可する-ディレクトリ内の参照が除去されていますが、データ(iノード)はフレッドの場合にのみ参照が到達する数0
ペンツ

いいえ、これはCentosにありました。
dtbarne 2015年

Linux 4.7.10でext4ファイルシステムを使用してテストしましたが、エラーは発生しませんでした。ファイルは正常に削除されました。多分dtbarneは特別なファイルシステムを使用しています。
k3a 2017年

これをvagrantで実行していた-共有フォルダーであることが原因である可能性があります。
dtbarne 2017年

0
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

回答としてコードだけを投稿するのではなく、コードが何をするか、それが質問の問題をどのように解決するかについての説明も提供してください。説明付きの回答は、通常、より効果的で質が高く、賛成票を集める可能性が高くなります。
Mark Rotteveel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.