web-dev-qa-db-ja.com

tar:ファイルを読むと変更されました

バックアップにmaketarを使用しています。 makefileを実行すると、tarコマンドはfile changed as we read itを表示します。この場合、

  • 警告が出たらtarパッケージは問題ありません
  • ただし、次のバックアップのtarコマンドは停止します
  • 実際に警告を示すファイルは変更されません-警告が表示されるのは本当に奇妙です
  • 警告を示すファイルはランダムに表示されます。つまり、メイクファイルを実行するたびに、警告を示すファイルが異なります
  • --ignore-failed-readは役に立ちません。 MinGWでtar 1.23を使用しています
  • コンピューターをWIN7 64ビットに変更しました。このスクリプトは、古いWIN7 32ビットでうまく機能します。ただし、tarバージョンは1.23ほど新しいものではありません。

警告の後にバックアップを停止するには、tarの警告を停止するにはどうすればよいですか?


編集-2:それが理由かもしれません

上で言ったように、bash Shellスクリプトは私の古いコンピューターでうまく機能しました。古いコンピューターと比較すると、msysバージョンは異なります。 tarコマンドのバージョンも同様です。古いコンピューターでは、tarは1.13.19で、新しいコンピューターでは1.23です。依存関係のmsys-1.0.dllを新しいコンピューターにコピーせずに古いtarコマンドをコピーし、名前をtar_oldに変更しました。また、シェルスクリプトのtarコマンドを更新し、スクリプトを実行しました。その後、すべてが大丈夫です。そのため、問題はtarコマンドにあるように見えました。風袋引きの際にファイルが変更されることはないと確信しています。新しいバージョンのtarコマンドのバグですか?知りません。


編集-1:詳細を追加

バックアップは、bashシェルスクリプトによって呼び出されます。ターゲットディレクトリをスキャンしてmakefileをビルドし、makeを呼び出してバックアップにtarコマンドを使用します。次に、bashシェルスクリプトによって作成された典型的なメイクファイルを示します。

#--------------------------------------------
# backup VC
#--------------------------------------------
# the program for packing
PACK_TOOL=tar

# the option for packing tool
PACK_OPTION=cjvf

# M$: C driver
WIN_C_DIR=c:

# M$: D driver
WIN_D_DIR=d:

# M$: where the software is
WIN_PRG_DIR=wuyu/tools
# WIN_PRG_DIR=

# where to save the backup files
BAKDIR=/home/Wu.Y/MS_bak_MSYS

VC_FRAMEWORK=/home/Wu.Y/MS_bak_MSYS/tools/VC/VC_framework.tar.bz2
VC_2010=/home/Wu.Y/MS_bak_MSYS/tools/VC/VC_2010.tar.bz2

.PHONY: all

all: $(VC_FRAMEWORK) $(VC_2010)

$(VC_FRAMEWORK): $(WIN_C_DIR)/$(WIN_PRG_DIR)/VC/Framework/*
    @$(PACK_TOOL) $(PACK_OPTION) "$@" --ignore-failed-read /c/$(WIN_PRG_DIR)/VC/Framework
$(VC_2010): $(WIN_C_DIR)/$(WIN_PRG_DIR)/VC/VS2010/*
    @$(PACK_TOOL) $(PACK_OPTION) "$@" --ignore-failed-read /c/$(WIN_PRG_DIR)/VC/VS2010

ご覧のとおり、tarパッケージは〜/ MS_bak_MSYS/tools/VC/VC_2010.tar.bz2に保存されています。 〜/ qqaaでスクリプトを実行します。 ~/MS_bak_MSYSはtarコマンドから除外されます。そのため、私が作成しているtarファイルは、tarファイルに入れようとしているディレクトリ内にありません。これが、警告が出たのがおかしいと感じた理由です。

56
warem

また、「読むと変更される」というtarメッセージが表示されます。私にとって、これらのメッセージは、bitbakeビルド環境でLinuxファイルシステムのtarファイルを作成していたときに発生しました。このエラーは散発的でした。

私にとって、これは同じディレクトリからtarファイルを作成したためではありません。実際には、tarファイルの作成中に上書きまたは変更されたファイルがあると想定しています。

メッセージは警告であり、tarファイルを作成します。オプションを設定することにより、これらの警告メッセージを抑制することができます

--warning=no-file-changed

http://www.gnu.org/software/tar/manual/html_section/warnings.html

それでも、警告メッセージの場合、tarが返す終了コードは「1」です。 http://www.gnu.org/software/tar/manual/html_section/Synopsis.html

したがって、スクリプト内の関数からtarファイルを呼び出す場合、次のような終了コードを処理できます。

set +e 
tar -czf sample.tar.gz dir1 dir2
exitcode=$?

if [ "$exitcode" != "1" ] && [ "$exitcode" != "0" ]; then
    exit $exitcode
fi
set -e
58
sandeep

非常に遅いですが、私は最近同じ問題を抱えていました。

問題は、コマンドの実行後に.が作成されるため、dir xyz.tar.gzが変更されるためです。 2つの解決策があります。

解決策1:tarは、.内の任意のディレクトリにアーカイブが作成されていてもかまいません。ワークスペース外でアーカイブを作成できない理由があります。次のようにアーカイブを置くための一時ディレクトリを作成することにより、この問題を回避しました。

mkdir artefacts
tar -zcvf artefacts/archive.tar.gz --exclude=./artefacts .
echo $?
0

解決策2:これが好きです。 tarを実行する前にアーカイブファイルを作成します。

touch archive.tar.gz
tar --exclude=archive.tar.gz -zcvf archive.tar.gz .
echo $?
0
31
Mohammad Azim

このような問題のデバッグを支援したい場合は、makeルールまたは少なくとも起動したtarコマンドを提供する必要があります。表示するコマンドがない場合、コマンドの何が問題なのかをどのように確認できますか?

ただし、99%の場合、このようなエラーは、tarファイルに配置しようとしているディレクトリ内にtarファイルを作成していることを意味します。そのため、tarはディレクトリを読み取ろうとすると、ディレクトリのメンバーとしてtarファイルを見つけ、tarファイルへの読み取りと書き込みを開始します。したがって、tarファイルの読み取りを開始してから終了するまでの間にtarファイルを読み取ると、tarファイルが変更されました。

たとえば、次のようなものです。

tar cf ./foo.tar .

間違っていないため、これを「停止」する方法はありません。 tarファイルを作成するときに別の場所に置くか、または--excludeなどを使用してtarファイルを省略します。

31
MadScientist

これは、tarの終了ステータスが1である場合にそれを無視するためのワンライナーです。 sandeepのスクリプト のようにset +eの必要はありません。 tar終了ステータスが0または1の場合、このワンライナーは終了ステータス0で戻ります。それ以外の場合、終了ステータス1で戻ります。これは、元の終了ステータス値が sandeepのスクリプト と異なる1と異なる場合は保持されます。

tar -czf sample.tar.gz dir1 dir2 || [[ $? -eq 1 ]]

16
Fabian Ritzmann

ファビアンのワンライナーを強化するため。終了ステータス1のみを無視し、それ以外の場合は終了ステータスを保持するとします。

tar -czf sample.tar.gz dir1 dir2 || ( export ret=$?; [[ $ret -eq 1 ]] || exit "$ret" )

これは、sandeepのスクリプトが行うすべてを1行で実行します。

2
Jeremy

出力に外部ディレクトリを使用するだけで、問題が解決しました。

Sudo tar czf ./../31OCT18.tar.gz ./
0