2010-10-18 19 views
10

Tôi có nhiệm vụ định kỳ tách một tập hợp lớn (khoảng 1-2 GiB mỗi) đã nén các tệp nhật ký Apache vào một số phần (nói các đoạn 500K dòng). Các tập tin cuối cùng nên được gzipped một lần nữa để hạn chế việc sử dụng đĩa.Phân tách các tệp nhật ký bị nén mà không lưu trữ các phân tách đã được giải nén trên đĩa

Trên Linux tôi sẽ thường làm:

zcat biglogfile.gz | split -l500000 

Các tập tin kết quả các file sẽ được đặt tên XAA, xab, xac, vv Vì vậy, tôi làm:

gzip x* 

Hiệu quả của phương pháp này là kết quả trung gian này là các tệp lớn được lưu trữ tạm thời trên đĩa. Có cách nào để tránh việc sử dụng đĩa trung gian này không?

Tôi có thể (theo cách tương tự với những gì xargs không) đã chia ống đầu ra thông qua lệnh (như gzip) và nén lại đầu ra khi đang di chuyển không? Hoặc tôi đang nhìn sai hướng và có cách nào tốt hơn để làm điều này?

Cảm ơn.

+0

Tôi sẽ xem xét triển khai chức năng tách kiểu theo ngôn ngữ kịch bản, nơi bạn có thể viết các dòng thẳng vào các tệp được nén. –

Trả lời

18

Bạn có thể sử dụng tùy chọn slpit --filter như được giải thích trong the manual ví dụ:

zcat biglogfile.gz | split -l500000 --filter='gzip > $FILE.gz' 

Edit: không biết khi --filter tùy chọn được giới thiệu nhưng theo ý kiến, nó không hoạt động trong core utils 8.4.

+1

Cảm ơn. Tôi nghĩ rằng việc sử dụng một tính năng chia nhỏ được thiết kế để thực hiện loại hoạt động này luôn tốt hơn mã nguồn gốc. –

+2

rất đẹp nhưng lưu ý rằng phân chia của coreutils 8.4 không có một 'lọc' argumnet – zach

+0

nhờ @zach tôi cập nhật câu trả lời – jimkont

-1

zipsplit, nhưng điều đó sử dụng thuật toán zip thay vì thuật toán gzip.

3

Một tập lệnh như sau có thể đủ.

#!/usr/bin/perl 
use PerlIO::gzip; 

$filename = 'out'; 
$limit = 500000; 

$fileno = 1; 
$line = 0; 

while (<>) { 
    if (!$fh || $line >= $limit) { 
     open $fh, '>:gzip', "$filename_$fileno"; 
     $fileno++; 
     $line = 0; 
    } 
    print $fh $_; $line++; 
} 
+0

Cảm ơn, ví dụ nhanh của bạn đã giúp tôi rất nhiều. Với hai sửa lỗi nhỏ (dòng đầu tiên phải bắt đầu bằng #!/Và sau khi $ fileno ++ thêm $ line = 0 là cần thiết) nó hoạt động đủ tốt cho mục đích của tôi. –

+0

Cảm ơn. Tôi đã thêm chúng vào kịch bản để hoàn thành. –

Các vấn đề liên quan