Điều quan trọng là phải hiểu rằng có một sự đánh đổi ở đây.
tar
có nghĩa là băng lưu trữ . Trên một băng, bạn chủ yếu đọc và viết tuần tự. Băng ngày nay hiếm khi được sử dụng, nhưng tar
vẫn được sử dụng cho khả năng đọc và ghi dữ liệu của nó dưới dạng luồng.
Bạn có thể làm:
tar cf - files | gzip | ssh host 'cd dest && gunzip | tar xf -'
Bạn không thể làm điều đó với zip
hoặc tương tự.
Bạn thậm chí không thể liệt kê nội dung của một zip
kho lưu trữ mà không lưu trữ cục bộ trong một tệp có thể tìm kiếm trước tiên. Suy nghĩ như:
curl -s https://github.com/dwp-forge/columns/archive/v.2016-02-27.zip | unzip -l /dev/stdin
sẽ không làm việc
Để đạt được việc đọc nhanh nội dung đó, zip
hoặc tương tự cần phải xây dựng một chỉ mục. Chỉ mục đó có thể được lưu trữ ở phần đầu của tệp (trong trường hợp đó chỉ có thể được ghi vào các tệp thông thường, không phải luồng) hoặc ở cuối, điều đó có nghĩa là người lưu trữ cần phải nhớ tất cả các thành viên lưu trữ trước khi in cuối và có nghĩa là một kho lưu trữ bị cắt ngắn có thể không thể phục hồi.
Điều đó cũng có nghĩa là các thành viên lưu trữ cần phải được nén riêng lẻ, điều đó có nghĩa là tỷ lệ nén thấp hơn nhiều, đặc biệt là nếu có nhiều tệp nhỏ.
Một nhược điểm khác với các định dạng như zip
là lưu trữ được liên kết với nén, bạn không thể chọn thuật toán nén. Xem cách tar
lưu trữ được sử dụng để nén với compress
( tar.Z
), sau đó gzip
, sau đó bzip2
, xz
khi các thuật toán nén hiệu suất mới được phát minh. Mã hóa cũng vậy. Ai sẽ tin tưởng zip
mã hóa ngày nay?
Bây giờ, vấn đề với tar.gz
tài liệu lưu trữ không nhiều đến mức bạn cần giải nén chúng. Việc giải nén thường nhanh hơn đọc hết đĩa (có thể bạn sẽ thấy rằng việc liệt kê nội dung của kho lưu trữ tgz lớn sẽ nhanh hơn khi liệt kê cùng một tệp không bị nén khi không lưu vào bộ nhớ), nhưng bạn cần đọc toàn bộ kho lưu trữ.
Không thể đọc chỉ mục một cách nhanh chóng không thực sự là một vấn đề. Nếu bạn thấy trước cần phải đọc nội dung bảng của một kho lưu trữ thường xuyên, bạn chỉ có thể lưu trữ danh sách đó trong một tệp riêng biệt. Chẳng hạn, tại thời điểm tạo, bạn có thể làm:
tar cvvf - dir 2> file.tar.xz.list | xz > file.tar.xz
Một vấn đề lớn hơn IMO là do khía cạnh tuần tự của kho lưu trữ, bạn không thể trích xuất các tệp riêng lẻ mà không đọc toàn bộ phần đầu của kho lưu trữ dẫn đến nó. IOW, bạn không thể đọc ngẫu nhiên trong kho lưu trữ.
Bây giờ, đối với các tệp có thể tìm kiếm, nó không phải theo cách đó.
Nếu bạn nén toàn bộ tar
kho lưu trữ của mình gzip
, nó nén toàn bộ, thuật toán nén sử dụng dữ liệu nhìn thấy lúc đầu để nén, do đó bạn phải bắt đầu từ đầu để giải nén.
Nhưng xz
định dạng có thể được cấu hình để nén dữ liệu theo từng phần riêng biệt (đủ lớn để quá trình nén có hiệu quả), điều đó có nghĩa là miễn là bạn giữ một chỉ mục ở cuối các đoạn được nén đó, đối với các tệp có thể tìm kiếm, bạn truy cập vào dữ liệu không nén ngẫu nhiên (ít nhất là trong khối).
pixz
(song song xz
) sử dụng khả năng đó khi nén tar
tài liệu lưu trữ để thêm chỉ mục bắt đầu của từng thành viên của kho lưu trữ ở cuối xz
tệp.
Vì vậy, đối với các tệp có thể tìm kiếm, bạn không chỉ có thể nhận được danh sách nội dung của kho lưu trữ tar ngay lập tức (không có siêu dữ liệu) nếu chúng đã được nén bằng pixz
:
pixz -l file.tar.xz
Nhưng bạn cũng có thể trích xuất các yếu tố riêng lẻ mà không cần phải đọc toàn bộ kho lưu trữ:
pixz -x archive/member.txt < file.tar.xz | tar xpf -
Bây giờ, về lý do tại sao những thứ như 7z
hoặc zip
hiếm khi được sử dụng trên Unix chủ yếu là vì chúng không thể lưu trữ các tệp Unix. Chúng đã được thiết kế cho các hệ điều hành khác. Bạn không thể thực hiện sao lưu dữ liệu trung thực bằng cách sử dụng dữ liệu đó. Họ không thể lưu trữ siêu dữ liệu như chủ sở hữu (id và tên), quyền, họ không thể lưu trữ liên kết tượng trưng, thiết bị, fifos ..., họ không thể lưu trữ thông tin về các liên kết cứng và thông tin siêu dữ liệu khác như thuộc tính mở rộng hoặc ACL.
Một số trong số họ thậm chí không thể lưu trữ các thành viên có tên tùy ý (một số sẽ bị nghẹt lại dấu gạch chéo ngược hoặc dòng mới hoặc dấu hai chấm hoặc tên tệp không phải mã ascii) (một số tar
định dạng cũng có những hạn chế).
Không bao giờ giải nén tệp tgz / tar.xz vào đĩa!
Trong trường hợp không rõ ràng, người ta không sử dụng tgz
hoặc tar.bz2
, tar.xz
... lưu trữ dưới dạng:
unxz file.tar.xz
tar tvf file.tar
xz file.tar
Nếu bạn có một .tar
tệp không nén nằm trên hệ thống tệp của mình, thì đó là bạn đã làm sai điều gì đó.
Toàn bộ điểm của những xz
/ bzip2
/ gzip
là máy nén dòng là chúng có thể được sử dụng khi đang bay, trong các đường ống như trong
unxz < file.tar.xz | tar tvf -
Mặc dù các tar
triển khai hiện đại biết cách tự gọi unxz
/ gunzip
/ bzip2
, vì vậy:
tar tvf file.tar.xz
nhìn chung cũng sẽ hoạt động (và một lần nữa giải nén dữ liệu một cách nhanh chóng và không lưu trữ phiên bản không nén của kho lưu trữ trên đĩa).
Thí dụ
Đây là một cây nguồn Linux được nén với nhiều định dạng khác nhau.
$ ls --block-size=1 -sS1
666210304 linux-4.6.tar
173592576 linux-4.6.zip
97038336 linux-4.6.7z
89468928 linux-4.6.tar.xz
Đầu tiên, như đã lưu ý ở trên, 7z và zip hơi khác nhau vì chúng không thể lưu trữ một vài liên kết tượng trưng trong đó và thiếu hầu hết các siêu dữ liệu.
Bây giờ một vài thời gian để liệt kê nội dung sau khi đã xóa bộ đệm hệ thống:
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ time tar tvf linux-4.6.tar > /dev/null
tar tvf linux-4.6.tar > /dev/null 0.56s user 0.47s system 13% cpu 7.428 total
$ time tar tvf linux-4.6.tar.xz > /dev/null
tar tvf linux-4.6.tar.xz > /dev/null 8.10s user 0.52s system 118% cpu 7.297 total
$ time unzip -v linux-4.6.zip > /dev/null
unzip -v linux-4.6.zip > /dev/null 0.16s user 0.08s system 86% cpu 0.282 total
$ time 7z l linux-4.6.7z > /dev/null
7z l linux-4.6.7z > /dev/null 0.51s user 0.15s system 89% cpu 0.739 total
Bạn sẽ nhận thấy việc liệt kê tar.xz
tệp nhanh hơn tệp .tar
thậm chí trên PC 7 tuổi này vì việc đọc thêm megabyte từ đĩa mất nhiều thời gian hơn đọc và giải nén tệp nhỏ hơn.
Sau đó, OK, liệt kê các tài liệu lưu trữ với 7z hoặc zip thì nhanh hơn nhưng đó không phải là vấn đề như tôi đã nói, nó dễ dàng được xử lý bằng cách lưu trữ danh sách tệp cùng với kho lưu trữ:
$ tar tvf linux-4.6.tar.xz | xz > linux-4.6.tar.xz.list.xz
$ ls --block-size=1 -sS1 linux-4.6.tar.xz.list.xz
434176 linux-4.6.tar.xz.list.xz
$ time xzcat linux-4.6.tar.xz.list.xz > /dev/null
xzcat linux-4.6.tar.xz.list.xz > /dev/null 0.05s user 0.00s system 99% cpu 0.051 total
Thậm chí nhanh hơn 7z hoặc zip ngay cả sau khi thả cache. Bạn cũng sẽ nhận thấy rằng kích thước tích lũy của kho lưu trữ và chỉ mục của nó vẫn nhỏ hơn lưu trữ zip hoặc 7z.
Hoặc sử dụng pixz
định dạng được lập chỉ mục:
$ xzcat linux-4.6.tar.xz | pixz -9 > linux-4.6.tar.pixz
$ ls --block-size=1 -sS1 linux-4.6.tar.pixz
89841664 linux-4.6.tar.pixz
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ time pixz -l linux-4.6.tar.pixz > /dev/null
pixz -l linux-4.6.tar.pixz > /dev/null 0.04s user 0.01s system 57% cpu 0.087 total
Bây giờ, để trích xuất các phần tử riêng lẻ của kho lưu trữ, trường hợp xấu nhất cho kho lưu trữ tar là khi truy cập vào phần tử cuối cùng:
$ xzcat linux-4.6.tar.xz.list.xz|tail -1
-rw-rw-r-- root/root 5976 2016-05-15 23:43 linux-4.6/virt/lib/irqbypass.c
$ time tar xOf linux-4.6.tar.xz linux-4.6/virt/lib/irqbypass.c | wc
257 638 5976
tar xOf linux-4.6.tar.xz linux-4.6/virt/lib/irqbypass.c 7.27s user 1.13s system 115% cpu 7.279 total
wc 0.00s user 0.00s system 0% cpu 7.279 total
Điều đó khá tệ vì nó cần phải đọc (và giải nén) toàn bộ kho lưu trữ. So sánh với:
$ time unzip -p linux-4.6.zip linux-4.6/virt/lib/irqbypass.c | wc
257 638 5976
unzip -p linux-4.6.zip linux-4.6/virt/lib/irqbypass.c 0.02s user 0.01s system 19% cpu 0.119 total
wc 0.00s user 0.00s system 1% cpu 0.119 total
Phiên bản 7z của tôi dường như không thể truy cập ngẫu nhiên, vì vậy nó dường như còn tồi tệ hơn tar.xz
:
$ time 7z e -so linux-4.6.7z linux-4.6/virt/lib/irqbypass.c 2> /dev/null | wc
257 638 5976
7z e -so linux-4.6.7z linux-4.6/virt/lib/irqbypass.c 2> /dev/null 7.28s user 0.12s system 89% cpu 8.300 total
wc 0.00s user 0.00s system 0% cpu 8.299 total
Bây giờ vì chúng tôi đã pixz
tạo một cái từ trước đó:
$ time pixz < linux-4.6.tar.pixz -x linux-4.6/virt/lib/irqbypass.c | tar xOf - | wc
257 638 5976
pixz -x linux-4.6/virt/lib/irqbypass.c < linux-4.6.tar.pixz 1.37s user 0.06s system 84% cpu 1.687 total
tar xOf - 0.00s user 0.01s system 0% cpu 1.693 total
wc 0.00s user 0.00s system 0% cpu 1.688 total
Nó nhanh hơn nhưng vẫn tương đối chậm vì kho lưu trữ chứa một vài khối lớn:
$ pixz -tl linux-4.6.tar.pixz
17648865 / 134217728
15407945 / 134217728
18275381 / 134217728
19674475 / 134217728
18493914 / 129333248
336945 / 2958887
Vì vậy, pixz
vẫn cần phải đọc và giải nén một khối dữ liệu lớn (tối đa a) ~ 19MB.
Chúng tôi có thể thực hiện truy cập ngẫu nhiên nhanh hơn bằng cách lưu trữ các khối nhỏ hơn (và hy sinh một chút dung lượng đĩa):
$ pixz -f0.25 -9 < linux-4.6.tar > linux-4.6.tar.pixz2
$ ls --block-size=1 -sS1 linux-4.6.tar.pixz2
93745152 linux-4.6.tar.pixz2
$ time pixz < linux-4.6.tar.pixz2 -x linux-4.6/virt/lib/irqbypass.c | tar xOf - | wc
257 638 5976
pixz -x linux-4.6/virt/lib/irqbypass.c < linux-4.6.tar.pixz2 0.17s user 0.02s system 98% cpu 0.189 total
tar xOf - 0.00s user 0.00s system 1% cpu 0.188 total
wc 0.00s user 0.00s system 0% cpu 0.187 total