tarを実行するとディスクがいっぱいになるかどうかを確認するにはどうすればよいですか


22

tar -cvfサイズ937MBのディレクトリで実行して、深くネストされたフォルダ構造の簡単にダウンロード可能なコピーを作成する場合、次のdf -h出力が与えられるとディスクがいっぱいになる危険があります。

/dev/xvda1            7.9G  3.6G  4.3G  46% /
tmpfs                 298M     0  298M   0% /dev/shm

関連する質問:

  • ディスクがいっぱいになる可能性がある場合、なぜLinux(Amazon AMI)および/または内部で何をするのtarでしょうか?
  • 再度尋ねることなく、この情報を自分で正確に判断するにはどうすればよいですか?

アーカイブを処理せずにそれが可能かどうかはわかりませんが、--totalsオプションでいろいろ試してみてください。いずれにせよ、ディスクがいっぱいになった場合、アーカイブ、imhoを削除するだけです。利用可能なすべてのオプションを確認するには、を実行できますtar --help
UVV 14

4
接線方向:tarfileをルートとして作成しないでください。ディスク上の特定の割合のスペースがルート専用として確保されます。 bash_historyまたは何でも」状況。
ウルリッヒ・シュワルツ14

回答:


24

tar -c data_dir | wc -c 圧縮なし

または

tar -cz data_dir | wc -c gzip圧縮あり

または

tar -cj data_dir | wc -c bzip2圧縮あり

ディスクに書き込まずに、作成されるアーカイブのサイズをバイト単位で出力します。次に、それをターゲットデバイスの空き容量と比較できます。

次のコマンドを使用すると、データディレクトリ自体のサイズを確認できます。そのサイズについて誤った仮定が行われた場合は、次のコマンドを使用します。

du -h --max-depth=1 data_dir

既に回答したように、tarはアーカイブ内の各レコードにヘッダーを追加し、各レコードのサイズを512バイトの倍数に切り上げます(デフォルト)。アーカイブの終わりは、少なくとも2つの連続したゼロで埋められたレコードによってマークされます。そのため、ファイル自体よりも大きい非圧縮tarファイルを使用する場合は常にそうです。ファイルの数と512バイト境界に合わせる方法によって、使用される余分なスペースが決まります。

もちろん、ファイルシステム自体は、個々のファイルのコンテンツよりも大きいブロックサイズを使用するため、tarを展開する場所に注意してください。tarサイズよりも大きな空きスペースがあっても、ファイルシステムは多くの小さなファイルを保持できない場合があります!

https://en.wikipedia.org/wiki/Tar_(computing)#Format_details


ジェイミーありがとう!ここで「-mysql」は何をしていますか?それはあなたのファイル名ですか?
codecowboy 14

それを変更しただけです...それはあなたのデータディレクトリへのパスです。
FantasticJamieBurns 14

1
本当に重要なことではありませんが、引数を組み合わせ-f -てtarに使用することは冗長です。なぜなら、-f引数を完全に省いて結果をstdout(つまりtar -c data_dir)に書き込むことができるからです。

6

tarファイルのサイズは、937MBに各ファイルまたはディレクトリに必要なメタデータのサイズ(オブジェクトごとに512バイト)、およびファイルを512バイト境界に揃えるために追加されるパディングになります。

非常に大まかな計算では、データの別のコピーによって3.4GBが無料になることがわかります。3.4GBには、パディングがないと仮定すると約700万個のメタデータレコードのスペースがあり、ファイルごとに平均256バイトのパディングがあると仮定するとそれより少なくなります。そのため、tarに何百万ものファイルとディレクトリがある場合、問題が発生する可能性があります。

次の方法で問題を緩和できます。

  • zまたはjオプションを使用してオンザフライで圧縮するtar
  • やってtar上の予約領域ように、通常のユーザーとして/あなたはスペースが不足した場合、パーティションが触れることはありません。

2

tar次の--testオプションを使用して、アーカイブ自体のサイズをレポートできます。

tar -cf - ./* | tar --totals -tvf -

上記のコマンドはディスクに何も書き込まず、tarballに含まれる各ファイルの個々のファイルサイズをリストするという追加の利点があります。さまざまなz/j/xzオペランドをいずれかの側に追加すると、 |pipe圧縮が処理されます。

出力:

...
-rwxr-xr-x mikeserv/mikeserv         8 2014-03-13 20:58 ./somefile.sh
-rwxr-xr-x mikeserv/mikeserv        62 2014-03-13 20:53 ./somefile.txt
-rw-r--r-- mikeserv/mikeserv       574 2014-02-19 16:57 ./squash.sh
-rwxr-xr-x mikeserv/mikeserv        35 2014-01-28 17:25 ./ssh.shortcut
-rw-r--r-- mikeserv/mikeserv        51 2014-01-04 08:43 ./tab1.link
-rw-r--r-- mikeserv/mikeserv         0 2014-03-16 05:40 ./tee
-rw-r--r-- mikeserv/mikeserv         0 2014-04-08 10:00 ./typescript
-rw-r--r-- mikeserv/mikeserv       159 2014-02-26 18:32 ./vlc_out.sh
Total bytes read: 4300943360 (4.1GiB, 475MiB/s)

目的は完全にはわかりませんが、tarballをダウンロードすることであれば、これはもっと重要なことです。

ssh you@host 'tar -cf - ./* | cat' | cat >./path/to/saved/local/tarball.tar

または、単純にコピーするにはtar

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -

これを行っている理由は、問題のディレクトリがdf -iの出力を99%に到達させたと考えているためです。私は、さらなる分析のためのディレクトリのコピーを保持したいが、スペースクリアしたい
codecowboy

@codecowboyその場合、最初に上記のようなことを必ず行う必要があります。それはされますtar、あなたがリモートホストからそれを削除し、後でそれを復元することができた後、すべてのリモートディスクには何も保存せずにストリームであなたのローカルディスクにツリーをコピーします。-z転送中の帯域幅を節約するために、goldilocksが指摘するように、おそらく圧縮を追加する必要があります。
mikeserv 14

@ TAFKA'goldilocks 'いいえ、99%のスペースではなく、99%のiノードです。
ジル「SO-悪であるのをやめる」14

-iはい、ごめんなさい!
goldilocks 14

@mikeservの最初の行には--testオプションが記載されていますが、すぐに続くコマンドでは使用しないようです(--totalsを使用)
codecowboy 14

2

私はこれについて多くの研究をしました。ワードカウントを使用してファイルのテストを実行できますが、aと同じ数値は得られませんdu -sb adir

tar -tvOf afile.tar | wc -c

duすべてのディレクトリを4096バイトとしてtarカウントし、ディレクトリを0バイトとしてカウントします。各ディレクトリに4096を追加する必要があります。

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096)))

その後、すべてのキャラクターを追加する必要があります。次のようなものの場合:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096 + $(tar -xOf afile.tar | wc -c) ))

触れられたファイル(0バイトのファイル)や1文字のファイルを試しなかったので、これが完璧かどうかはわかりません。これにより、より近くになります。


1

-cvf圧縮を含まないため、〜1 GBフォルダーでこれを実行すると〜1 GBのtarファイルになります(Flubの回答にはtarファイルの追加サイズに関する詳細が記載されていますが、10,000個のファイルがある場合でも、これは5 MB)。4 GB以上の空き容量があるため、パーティションを埋めることはできません。

簡単にダウンロードできるコピー

ほとんどの人は、ダウンロードに関して「簡単」と「小さい」を同義語と見なすため、ここで圧縮を使用する必要があります。 bzip2現在、tarを備えたすべてのシステムで利用できるはずです。したがってj、スイッチに含めるのがおそらく最良の選択です。 zgzip)はおそらくより一般的であり、よりスカッシュのある(ユビキタスではない)他の可能性があります。

あなたが意味する場合は、ありませんtar私はかなり確信して、それはいくつかの理由のために、1は、テープドライブは、プライマリストレージの形だったとき、それが戻って時間にさかのぼること、および2つのそれは持っていることはありませんよ、一時的にタスクを実行する際に、追加のディスク領域を使用何十年も進化していました(そして、圧縮が関係していても、一時的な中間スペースを使用する必要はないと確信しています)。


0

速度が重要で圧縮が不要な場合は、を使用しtarて使用するsyscallラッパーをフックしLD_PRELOAD、変更tarして計算してください。私たちのニーズに合わせて、これらの機能のいくつかを再実装することにより(電位出力タールデータのサイズを計算する)、我々は多くのを排除することができますreadし、writeそれは、通常の操作で行われますtar。これによりtar、コンテキストスイッチを前後にカーネルに前後に切り替える必要がなくなりstat、実際のファイルデータではなく、要求された入力ファイル/フォルダーのみをディスクから読み取る必要があるため、はるかに高速になります。

コードは以下の実装含みclosereadおよびwritePOSIX機能を。このマクロOUT_FDtar、出力ファイルとして使用するファイル記述子を制御します。現在、標準出力に設定されています。

readcount実際のデータが読み取られなかった場合、bufに圧縮を渡すための有効なデータが含まれていないため、bufにデータを入力する代わりに、バイトの成功値を返すように変更されました。サイズ。

write入力countバイトをグローバル変数に合計し、ファイル記述子が一致する場合のみバイトtotalの成功値を返すように変更されました。そうでない場合は、経由で取得した元のラッパーを呼び出して同じ名前のsyscallを実行します。countOUT_FDdlsym

closeそれでも元の機能はすべて実行されますが、ファイル記述子がOUT_FDと一致する場合、tartarファイルへの書き込みの試行が完了したことを認識しているため、total番号は最終的なものであり、stdoutに出力されます。

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>

#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
    printf("%" PRIu64 "\n", total);
}

int close(int fd)
{
    if(! original_close)
    {
        original_close = dlsym(RTLD_NEXT, "close");
    }
    if(fd == OUT_FD)
    {
        print_total();
    }
    return original_close(fd);
}

ssize_t read(int fd, void *buf, size_t count)
{
    return count;
}

ssize_t write(int fd, const void *buf, size_t count)
{
    if(!original_write)
    {
        original_write = dlsym(RTLD_NEXT, "write");
    }
    if(fd == OUT_FD)
    {
        total += count;
        return count;
    }
    return original_write(fd, buf, count);
}

読み取りディスクアクセスと通常のtar操作のすべてのsyscallsがLD_PRELOADソリューションに対して実行されるソリューションを比較するベンチマーク。

$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real    0m0.457s
user    0m0.064s
sys     0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real    0m0.016s
user    0m0.004s
sys     0m0.008s

上記のコード、上記を共有ライブラリとしてビルドするための基本的なビルドスクリプト、およびLD_PRELOADそれを使用する「テクニック」を備えたスクリプトがレポジトリで提供されていますhttps : //github.com/G4Vi/tarsize

LD_PRELOADの使用に関する情報:https : //rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/


コードは機能していれば良いのですが、その機能を説明できますか?コメントで返信しないでください。 回答を編集して、より明確で完全なものにします。
G-Manが「Reinstate Monica」と
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.