Tại sao tar xuất hiện để bỏ qua nội dung tệp khi tệp đầu ra là / dev / null?


21

Tôi có một thư mục chứa hơn 400 GiB dữ liệu trong đó. Tôi muốn kiểm tra xem tất cả các tập tin có thể được đọc mà không có lỗi, vì vậy một cách đơn giản mà tôi nghĩ là đưa tarnó vào /dev/null. Nhưng thay vào đó tôi thấy hành vi sau:

$ time tar cf /dev/null .

real    0m4.387s
user    0m3.462s
sys     0m0.185s
$ time tar cf - . > /dev/null

real    0m3.130s
user    0m3.091s
sys     0m0.035s
$ time tar cf - . | cat > /dev/null
^C

real    10m32.985s
user    0m1.942s
sys     0m33.764s

Lệnh thứ ba ở trên đã bị buộc dừng lại bởi Ctrl+ Csau khi đã chạy khá lâu. Hơn nữa, trong khi hai lệnh đầu tiên đang hoạt động, chỉ báo hoạt động của thiết bị lưu trữ chứa .gần như luôn ở chế độ chờ. Với lệnh thứ ba, đèn báo liên tục sáng lên, nghĩa là sự bận rộn cực độ.

Vì vậy, có vẻ như, khi tarcó thể phát hiện ra rằng tệp đầu ra của nó là /dev/null, tức là khi /dev/nullđược mở trực tiếp để có tệp xử lý targhi vào, phần thân tệp xuất hiện bị bỏ qua. (Thêm vtùy chọn để tarin tất cả các tệp trong thư mục có tarmàu đỏ.)

Vì vậy, tôi tự hỏi, tại sao điều này là như vậy? Đây có phải là một loại tối ưu hóa? Nếu có, thì tại sao tarthậm chí muốn thực hiện một tối ưu hóa đáng ngờ cho một trường hợp đặc biệt như vậy?

Tôi đang sử dụng GNU tar 1.26 với glibc 2.27 trên Linux 4.14.105 amd64.


7
Là một thay thế thực tế, xem xét một cái gì đó như find . -type f -exec shasum -a256 -b '{}' +. Nó không chỉ thực sự đọc và kiểm tra tất cả dữ liệu, mà nếu bạn lưu trữ đầu ra, bạn có thể chạy lại nó sau để kiểm tra xem nội dung của các tệp đã thay đổi.
Ilmari Karonen

Để đo lường những thứ bạn cũng có thể sử dụng pv: tar -cf - | pv >/dev/null. Điều đó khắc phục vấn đề và cung cấp cho bạn thông tin tiến trình (các pvtùy chọn khác nhau )
xenoid

Bạn nhấn một tính năng bỏ lỡ nổi tiếng của GNU tar. Sử dụng gtar -cf /dev/zero ...để có được những gì bạn thích.
schily

Câu trả lời:


25

Đây một tối ưu hóa tài liệu :

Khi kho lưu trữ được tạo ra /dev/null, GNU tar cố gắng giảm thiểu các hoạt động đầu vào và đầu ra. Hệ thống sao lưu Amanda, khi được sử dụng với GNU tar, có một đường dẫn kích thước ban đầu sử dụng tính năng này.


4
Ah, điều này không được mô tả trong trang người đàn ông tôi đã cài đặt. info tarThay vào đó nên thử ...
Ruslan

9
Họ thực sự nên giữ đồng bộ trang người đàn ông và thông tin, thực tế đó là một lỗi mà họ không phải
Xen2050

9
@Ruslan Với hầu hết các tiện ích GNU, trang man chỉ chứa một bản tóm tắt ngắn gọn, về cơ bản chỉ đủ tốt khi bạn nhớ rằng nó có một tùy chọn để làm một cái gì đó nhưng không nhớ tên của tùy chọn. Tài liệu hoàn chỉnh có định dạng không dịch tốt sang các trang man và có sẵn với infohoặc dưới dạng HTML trong trình duyệt.
Gilles 'SO- ngừng trở nên xấu xa'


8

Điều này có thể xảy ra với một loạt các chương trình, ví dụ, tôi đã có hành vi đó một lần khi chỉ sử dụng cp file /dev/null; thay vì ước tính tốc độ đọc đĩa của tôi, lệnh được trả về sau vài mili giây.

Theo tôi nhớ, đó là trên Solaris hoặc AIX, nhưng nguyên tắc này áp dụng cho tất cả các loại hệ thống unix-y.

Vào thời xưa, khi một chương trình sao chép một tệp vào một nơi nào đó, nó sẽ xen kẽ giữa readcác cuộc gọi lấy một số dữ liệu từ đĩa (hoặc bất cứ điều gì mà bộ mô tả tệp đang đề cập đến) vào bộ nhớ (với sự đảm bảo mọi thứ đều có khi readtrả về) và writegọi (trong đó lấy đoạn bộ nhớ và gửi nội dung đến đích).

Tuy nhiên, có ít nhất hai cách mới hơn để đạt được cùng một:

  • Linux có các cuộc gọi hệ thống copy_file_range(hoàn toàn không thể di chuyển đến các unix khác) và sendfile(hơi di động; ban đầu dự định gửi một tệp tới mạng, nhưng có thể sử dụng bất kỳ đích nào ngay bây giờ). Họ dự định tối ưu hóa chuyển khoản; nếu chương trình sử dụng một trong số đó, thì hạt nhân có thể dễ dàng nhận ra được mục tiêu /dev/nullvà biến cuộc gọi hệ thống thành không hoạt động

  • Các chương trình có thể sử dụng mmapđể lấy nội dung tệp thay vì read, về cơ bản có nghĩa là "đảm bảo dữ liệu ở đó khi tôi cố truy cập vào đoạn bộ nhớ đó" thay vì "đảm bảo dữ liệu ở đó khi cuộc gọi hệ thống trở lại". Vì vậy, một chương trình có thể mmaplà tệp nguồn, sau đó gọi writevào đoạn bộ nhớ được ánh xạ đó. Tuy nhiên, vì văn bản /dev/nullkhông cần truy cập vào dữ liệu bằng văn bản, điều kiện "đảm bảo rằng nó không bao giờ được kích hoạt, dẫn đến việc tệp cũng không được đọc.

Không chắc chắn nếu gnu tar sử dụng bất kỳ, và cơ chế nào trong hai cơ chế này khi phát hiện ra nó đang ghi /dev/null, nhưng chúng là lý do tại sao mọi chương trình, khi được sử dụng để kiểm tra tốc độ đọc , nên được chạy | cat > /dev/nullthay vì > /dev/null- và tại sao | cat > /dev/nullnên chạy được tránh trong tất cả các trường hợp khác.


Tôi nghĩ hàm ý trong tartrang thông tin GNU (xem câu trả lời khác) là nó có chế độ đặc biệt cho việc này, có lẽ chỉ là các tệp thống kê mà không cần mở chúng. Trong thực tế, tôi chỉ kiểm tra tar cf /dev/null foo*trên một vài tệp và vâng, chỉ là newfstatat(..., AT_SYMLINK_NOFOLLOW)các cuộc gọi hệ thống, thậm chí không phải là một open()bản cập nhật. Nhưng +1 để mô tả các cơ chế trong đó điều này có thể xảy ra mà không cần phải phát hiện đặc biệt.
Peter Cordes

Có nên giải thích mmap "truy cập dữ liệu đã đọc " thay vì "truy cập dữ liệu bằng văn bản ?"
Wayne Conrad

Xem thêm splice(2)trên Linux. Trên thực tế, việc thay thế, cat > /dev/nullbằng pv -q > /dev/null(sử dụng splice()trên Linux) có thể sẽ giảm chi phí. Hoặc dd bs=65536 skip=9999999999 2> /dev/null, hay wc -c > /dev/nullhay tail -c1 > /dev/null...
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.