Cách thêm một tệp khổng lồ vào kho lưu trữ và xóa song song


8

Giả sử tôi có tệp 80 /root/bigfileGB trên hệ thống 100 GB và muốn đặt tệp này vào kho lưu trữ /root/bigarchive.tar

Tôi rõ ràng cần phải xóa tập tin này cùng lúc với nó được thêm vào trong kho lưu trữ. Do đó câu hỏi của tôi:

Làm thế nào để xóa một tập tin cùng lúc với nó được thêm vào trong một kho lưu trữ?

Câu trả lời:


0

Nếu bạn đang sử dụng tarlệnh GNU , bạn có thể sử dụng --remove-filestùy chọn:

--xoá những tập tin

xóa các tập tin sau khi thêm chúng vào kho lưu trữ

tar -cvf files.tar --remove-files my_directory

5
Tôi nghĩ rằng OP muốn xóa tệp cùng lúc nó được lưu trữ, vì vậy nếu --remove-files xóa sau khi thêm tệp vào .tar, nó sẽ không hữu ích cho anh ta vì đĩa cứng của anh ta sẽ hết không gian.
Zumo de Vidrio

6

Một kho lưu trữ tar không nén của một tệp bao gồm một tiêu đề, tệp và một dấu kiểm. Vì vậy, vấn đề chính của bạn là làm thế nào để thêm 512 byte tiêu đề vào đầu tệp của bạn. Bạn có thể bắt đầu bằng cách tạo kết quả mong muốn chỉ bằng tiêu đề:

tar cf - bigfile | dd count=1 >bigarchive.tar

Sau đó sao chép 10G đầu tiên của tệp của bạn. Để đơn giản, chúng tôi giả sử dd của bạn có thể đọc / ghi 1Gib cùng một lúc:

dd count=10 bs=1G if=bigfile >>bigarchive.tar

Bây giờ chúng tôi sắp xếp lại dữ liệu đã sao chép từ tệp gốc:

fallocate --punch-hole -o 0 -l 10GiB bigfile

Điều này thay thế dữ liệu bằng các số 0 thưa thớt không chiếm dung lượng trên hệ thống tập tin. Tiếp tục theo cách này, thêm một skip=10vào tiếp theo dd, và sau đó tăng phần fallocatebù bắt đầu lên -o 10GiB. Cuối cùng, thêm một số ký tự nul để điền vào tệp tar cuối cùng.


Nếu hệ thống tệp của bạn không hỗ trợ, fallocatebạn có thể làm điều gì đó tương tự, nhưng bắt đầu từ cuối tệp. Đầu tiên sao chép 10Gibytes cuối cùng của tệp vào một tệp trung gian có tên là, giả sử part8. Sau đó sử dụng truncatelệnh để giảm kích thước của tệp gốc. Tiến hành tương tự cho đến khi bạn có 8 tệp mỗi tệp 10Gibyte. Sau đó bạn có thể nối các header và part1đến bigarchive.tar, sau đó loại bỏ part1, và sau đó tiếp nhau part2và loại bỏ nó, và vân vân.


5

Xóa một tập tin không nhất thiết phải làm những gì bạn nghĩ nó làm. Đó là lý do tại sao trong các hệ thống giống như UNIX, cuộc gọi hệ thống được gọi unlinkvà không delete. Từ trang hướng dẫn:

unlink() deletes a name from the filesystem.  If that name was the last
link to a file and no processes have the file open, the file is deleted
and the space it was using is made available for reuse.

If the name was the last link to a file but any processes still have
the file open, the file will remain in existence until  the  last  file
descriptor referring to it is closed.

Kết quả là, miễn là trình nén / lưu trữ dữ liệu đang đọc từ tệp, tệp đó vẫn tồn tại, chiếm không gian trong hệ thống tệp.


1

Làm thế nào để xóa một tập tin cùng lúc với nó được thêm vào trong một kho lưu trữ?

Với bối cảnh, tôi sẽ giải thích câu hỏi này là:

Cách xóa dữ liệu khỏi đĩa ngay sau khi đọc, trước khi đọc toàn bộ tệp, để có đủ không gian cho tệp được chuyển đổi.

Việc chuyển đổi có thể là bất cứ điều gì bạn muốn làm với dữ liệu: nén, mã hóa, v.v.

Câu trả lời là đây:

<$file gzip | dd bs=$buffer iflag=fullblock of=$file conv=notrunc

Tóm lại: đọc dữ liệu, ném nó vào gzip (hoặc bất cứ điều gì bạn muốn làm với nó), đệm đầu ra để chúng tôi chắc chắn đọc nhiều hơn chúng ta viết và ghi lại vào tệp. Đây là phiên bản đẹp hơn và hiển thị đầu ra trong khi chạy:

cat "$file" \
| pv -cN 'bytes read from file' \
| gzip \
| pv -cN 'bytes received from compressor' \
| dd bs=$buffer iflag=fullblock 2>/dev/null \
| pv -cN 'bytes written back to file' \
| dd of="$file" conv=notrunc 2>/dev/null

Tôi sẽ đi qua nó, từng dòng một:

cat "$file"đọc tập tin bạn muốn nén Đó là một cách sử dụng mèo vô dụng (UUOC) vì phần tiếp theo, pv, cũng có thể đọc tệp, nhưng tôi thấy điều này là đẹp hơn.

Nó đưa nó vào pvtrong đó hiển thị thông tin tiến trình ( -cNnói với nó 'sử dụng một số loại [c] con trỏ' và cung cấp cho nó [N] ame).

Đó là đường ống gzipmà rõ ràng là nén (đọc từ stdin, xuất ra stdout).

Mà ống vào khác pv(xem ống).

Mà ống vào dd bs=$buffer iflag=fullblock. Các $bufferbiến là một số, một cái gì đó giống như 50 MB. Tuy nhiên, đó là nhiều RAM bạn muốn dành cho việc xử lý an toàn tệp của bạn (như một điểm dữ liệu, bộ đệm 50 MB cho tệp 2 GB là ổn). Các iflag=fullblockkể ddđể đọc lên đến $bufferbyte trước khi đường ống thông qua. Ban đầu, gzip sẽ viết một tiêu đề, vì vậy đầu ra của gzip sẽ nằm trong dddòng này . Sau đó ddsẽ đợi cho đến khi nó có đủ dữ liệu trước khi chuyển qua, và vì vậy đầu vào có thể đọc thêm. Hơn nữa, nếu bạn có các phần không thể nén, tệp đầu ra có thể lớn hơn tệp đầu vào. Bộ đệm này đảm bảo rằng, lên đến $bufferbyte, đây không phải là vấn đề.

Sau đó, chúng tôi đi vào một dòng xem ống khác, và cuối cùng vào dddòng đầu ra của chúng tôi . Dòng này có of(tệp đầu ra) và conv=notruncđược chỉ định, trong đó notruncyêu cầu ddkhông cắt bớt (xóa) tệp đầu ra trước khi viết. Vì vậy, nếu bạn có 500 byte Avà bạn viết 3 byte B, tệp sẽ là BBBAAAAA...(thay vì được thay thế bởi BBB).

Tôi đã không bao gồm các 2>/dev/nullphần, và chúng không cần thiết. Họ chỉ thu dọn đầu ra một chút bằng cách chặn thông ddbáo "Tôi đã hoàn thành và viết nhiều byte" này. Các dấu gạch chéo ngược ở cuối mỗi dòng ( \) làm cho bash coi toàn bộ là một lệnh lớn nối với nhau.


Đây là một kịch bản đầy đủ để sử dụng dễ dàng hơn. Thông thường, tôi đặt nó vào một thư mục có tên 'gz-in-place'. Sau đó tôi nhận ra từ viết tắt mà tôi đã tạo ra: GZIP: gnu zip tại chỗ. Vì vậy, tôi xin trình bày, GZIP.sh:

#!/usr/bin/env bash

### Settings

# Buffer is how many bytes to buffer before writing back to the original file.
# It is meant to prevent the gzip header from overwriting data, and in case
# there are parts that are uncompressible where the compressor might exceed
# the original filesize. In these cases, the buffer will help prevent damage.
buffer=$((1024*1024*50)) # 50 MiB

# You will need something that can work in stream mode from stdin to stdout.
compressor="gzip"

# For gzip, you might want to pass -9 for better compression. The default is
# (typically?) 6.
compressorargs=""

### End of settings

# FYI I'm aware of the UUOC but it's prettier this way

if [ $# -ne 1 ] || [ "x$1" == "x-h" ] || [ "x$1" == "x--help" ]; then
    cat << EOF
Usage: $0 filename
Where 'filename' is the file to compress in-place.

NO GUARANTEES ARE GIVEN THAT THIS WILL WORK!
Only operate on data that you have backups of.
(But you always back up important data anyway, right?)

See the source for more settings, such as buffer size (more is safer) and
compression level.

The only non-standard dependency is pv, though you could take it out
with no adverse effects, other than having no info about progress.
EOF
    exit 1;
fi;

b=$(($buffer/1024/1024));
echo "Progressing '$1' with ${b}MiB buffer...";
echo "Note: I have no means of detecting this, but if you see the 'bytes read from";
echo "file' exceed 'bytes written back to file', your file is now garbage.";
echo "";

cat "$1" \
| pv -cN 'bytes read from file' \
| $compressor $compressorargs \
| pv -cN 'bytes received from compressor' \
| dd bs=$buffer iflag=fullblock 2>/dev/null \
| pv -cN 'bytes written back to file' \
| dd of="$1" conv=notrunc 2>/dev/null

echo "Done!";

Tôi cảm thấy muốn thêm một dòng đệm khác trước gzip, để ngăn nó viết quá xa khi dddòng đệm lướt qua, nhưng chỉ với bộ đệm 50MiB và 1900MB /dev/urandomdữ liệu, dường như nó vẫn hoạt động (md5sums phù hợp sau khi giải nén). Tỷ lệ đủ tốt cho tôi.

Một cải tiến khác sẽ là phát hiện viết quá xa, nhưng tôi không thấy cách thực hiện mà không loại bỏ vẻ đẹp của thứ đó và tạo ra nhiều sự phức tạp. Tại thời điểm đó, bạn cũng có thể biến nó thành một chương trình python hoàn chỉnh, thực hiện đúng tất cả (với failafes để ngăn chặn phá hủy dữ liệu).

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.