ฉันจะทราบได้อย่างไรว่าการรัน tar จะทำให้ดิสก์เติมเต็ม


22

ถ้าฉันเรียกใช้tar -cvfในไดเรกทอรีขนาด 937MB เพื่อสร้างสำเนาของโครงสร้างโฟลเดอร์ที่ซ้อนกันที่สามารถดาวน์โหลดได้อย่างง่ายดายฉันจะเสี่ยงต่อการเติมดิสก์ตามdf -hผลลัพธ์ดังนี้

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

คำถามที่เกี่ยวข้อง:

  • หากดิสก์เติมเต็มทำไมลินุกซ์ (Amazon AMI) และ / หรือtarกำลังทำอะไรอยู่ใต้ฝากระโปรง?
  • ฉันจะตรวจสอบข้อมูลนี้อย่างถูกต้องได้อย่างไรโดยไม่ต้องถามอีก

ฉันไม่แน่ใจว่าเป็นไปได้หรือไม่หากไม่ประมวลผลไฟล์เก็บถาวร แต่คุณสามารถเลือกเล่น--totalsได้ ถ้าคุณเติมดิสก์ด้วยวิธีใดคุณก็สามารถลบไฟล์เก็บถาวรได้ทันที tar --helpในการตรวจสอบตัวเลือกทั้งหมดที่มีอยู่คุณอาจจะผ่านไป
UVV

4
อย่างเป็นรูปธรรม: อย่าสร้าง tarfile ในฐานะ root เปอร์เซ็นต์ของพื้นที่บนดิสก์ถูกตั้งค่าไว้สำหรับ root โดยเฉพาะอย่างยิ่งสำหรับประเภทของ "ฉันเติมดิสก์แล้วและตอนนี้ฉันไม่สามารถเข้าสู่ระบบได้เพราะนั่นจะเขียน bash_history หรือสถานการณ์ "อะไรก็ได้
Ulrich Schwarz

คำตอบ:


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 ไบต์ (โดยค่าเริ่มต้น) จุดสิ้นสุดของการเก็บถาวรถูกทำเครื่องหมายด้วยระเบียนที่กรอกข้อมูลศูนย์อย่างน้อยสองรายการติดต่อกัน ดังนั้นจึงเป็นกรณีที่คุณจะมีไฟล์ tar ที่ไม่มีการบีบอัดขนาดใหญ่กว่าไฟล์ตัวเองจำนวนไฟล์และวิธีที่พวกเขาจัดตำแหน่งขอบเขต 512 ไบต์กำหนดพื้นที่พิเศษที่ใช้

แน่นอนว่าระบบไฟล์ใช้ขนาดบล็อกที่อาจใหญ่กว่าเนื้อหาของไฟล์แต่ละไฟล์ดังนั้นควรระวังในกรณีที่คุณไม่ได้ทำการติดตั้งระบบไฟล์อาจไม่สามารถเก็บไฟล์ขนาดเล็กจำนวนมากได้แม้ว่าจะมีพื้นที่ว่างมากกว่าขนาด tar!

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


ขอบคุณเจมี่! '- mysql' กำลังทำอะไรที่นี่ นั่นคือชื่อไฟล์ของคุณหรือไม่
codecowboy

เพิ่งเปลี่ยนที่ ... มันเป็นเส้นทางไปยังไดเรกทอรีข้อมูลของคุณ
FantasticJamieBurns

1
ไม่ว่าจะเป็นเรื่องสำคัญ แต่การใช้ชุดค่าผสมอาร์กิวเมนต์-f -เพื่อ tar นั้นซ้ำซ้อนเนื่องจากคุณสามารถละทิ้ง-fอาร์กิวเมนต์ทั้งหมดพร้อมกันเพื่อเขียนผลลัพธ์ไปยัง stdout (เช่นtar -c data_dir)

6

ขนาดของไฟล์ tar ของคุณจะเป็น 937MB บวกขนาดของข้อมูลเมตาที่จำเป็นสำหรับแต่ละไฟล์หรือไดเรกทอรี (512 ไบต์ต่อวัตถุ) และเพิ่มช่องว่างภายในเพื่อจัดแนวไฟล์ให้เป็นขอบเขต 512- ไบต์

การคำนวณคร่าวๆบอกเราว่าอีกสำเนาของข้อมูลของคุณจะทำให้คุณว่าง 3.4GB ใน 3.4GB เรามีพื้นที่สำหรับบันทึกข้อมูลเมตาประมาณ 7 ล้านรายการโดยไม่มีการเว้นระยะห่างหรือน้อยกว่าหากคุณคิดว่าการแพ็ดเฉลี่ย 256 ไบต์ต่อไฟล์ ดังนั้นหากคุณมีไฟล์และไดเรคทอรีให้เลือกหลายล้านไฟล์คุณอาจพบปัญหา

คุณสามารถลดปัญหาโดย

  • บีบอัดได้ทันทีโดยใช้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

@ TAFKA'goldilocks 'ไม่เพราะมันเป็น 99% ของ inodes ไม่ใช่ 99% ของพื้นที่
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

-iถูกต้องขอโทษ!
goldilocks

@mikeserv บรรทัดเปิดของคุณกล่าวถึงตัวเลือก --test แต่ดูเหมือนว่าคุณจะไม่ใช้มันในคำสั่งของคุณซึ่งจะตามมาทันที (ใช้
codecowboy

2

ฉันได้ทำการวิจัยมากมายเกี่ยวกับเรื่องนี้ คุณสามารถทำแบบทดสอบในแฟ้มที่มีการนับจำนวนคำ 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 จะส่งผลให้ไฟล์ tar ~ 1 GB (คำตอบของ Flub มีรายละเอียดเพิ่มเติมเกี่ยวกับขนาดเพิ่มเติมในไฟล์ tar แต่โปรดทราบแม้ว่าจะมี 10,000 ไฟล์นี่เป็นเพียง 5 MB) เนื่องจากคุณมีฟรี 4+ GB คุณจะไม่เติมพาร์ติชั่น

สำเนาที่ดาวน์โหลดได้ง่าย

คนส่วนใหญ่จะพิจารณาคำพ้องความหมาย "ง่ายขึ้น" กับ "เล็กกว่า" ในแง่ของการดาวน์โหลดดังนั้นคุณควรใช้การบีบอัดที่นี่ bzip2ตอนนี้ควรจะพร้อมใช้งานในระบบใด ๆ ก็ตามโดยที่ฉันคิดว่าการรวมjสวิตช์ของคุณน่าจะเป็นตัวเลือกที่ดีที่สุด z( gzip) อาจพบได้บ่อยกว่าและมีความเป็นไปได้อื่น ๆ (แพร่หลายน้อยกว่า) ด้วยสควอชมากขึ้น

ถ้าคุณหมายความว่าtarใช้พื้นที่ว่างดิสก์เพิ่มเติมชั่วคราวในการทำงานฉันค่อนข้างแน่ใจว่ามันไม่ได้ด้วยเหตุผลสองสามประการประการหนึ่งคือมันมีอายุย้อนหลังไปเมื่อเทปไดรฟ์เป็นรูปแบบของที่เก็บข้อมูลหลัก มีทศวรรษที่จะพัฒนา (และฉันแน่ใจว่ามันไม่จำเป็นต้องใช้พื้นที่กลางชั่วคราวแม้ว่าจะมีการบีบอัดที่เกี่ยวข้อง)


0

ถ้าความเร็วเป็นสิ่งที่สำคัญและการบีบอัดไม่จำเป็นต้องคุณสามารถขอห่อ syscall ที่ใช้โดยtarใช้LD_PRELOADการเปลี่ยนแปลงtarในการคำนวณนั้นเรา โดย reimplementing ไม่กี่ของฟังก์ชั่นเหล่านี้เพื่อให้เหมาะกับความต้องการของเรา (คำนวณขนาดของข้อมูลการส่งออกที่มีศักยภาพ tar) เราสามารถกำจัดจำนวนมากreadและการที่จะดำเนินการในการดำเนินงานตามปกติของwrite tarสิ่งนี้ทำให้tarเร็วขึ้นมากเนื่องจากไม่จำเป็นต้องสลับบริบทไปมาในเคอร์เนลที่ใดก็ตามที่อยู่ใกล้มากและมีเพียงstatไฟล์ / โฟลเดอร์ที่ร้องขอเท่านั้นที่จำเป็นต้องอ่านจากดิสก์แทนที่จะเป็นข้อมูลไฟล์จริง

โค้ดข้างล่างนี้รวมถึงการใช้งานของclose, readและwriteฟังก์ชั่น POSIX แมโครOUT_FDควบคุมไฟล์ descriptor ที่เราคาดว่าtarจะใช้เป็นไฟล์เอาต์พุต ขณะนี้มันถูกตั้งค่าเป็น stdout

readเปลี่ยนเป็นเพียงคืนค่าความสำเร็จของcountไบต์แทนการเติม buf ด้วยข้อมูลเนื่องจากข้อมูลจริงที่ไม่ได้อ่าน buf จะไม่มีข้อมูลที่ถูกต้องสำหรับการส่งผ่านไปยังการบีบอัดและดังนั้นหากการบีบอัดถูกใช้เราจะคำนวณว่าไม่ถูกต้อง ขนาด.

writeถูกเปลี่ยนเพื่อรวมcountไบต์อินพุตลงในตัวแปรโกลบอลtotalและส่งคืนค่าความสำเร็จของcountไบต์เฉพาะเมื่อไฟล์ descriptor ตรงกันOUT_FDมิฉะนั้นจะเรียก wrapper ดั้งเดิมที่ได้มาจากdlsymการดำเนินการ syscall ในชื่อเดียวกัน

closeยัง preforms ฟังก์ชั่นดั้งเดิมทั้งหมด แต่ถ้า file descriptor ตรงกับ OUT_FD จะรู้ว่าtarพยายามเขียนไฟล์ tar ดังนั้น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);
}

การเปรียบเทียบเกณฑ์เปรียบเทียบโซลูชันที่การอ่านดิสก์การเข้าถึงและ syscalls ทั้งหมดของการดำเนินการ tar ปกติจะดำเนินการกับ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เทคนิค" การใช้งานจะมีให้ใน repo: 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.