Vì vậy, gần đây tôi muốn làm điều này với tar
. Một số điều tra chỉ ra cho tôi rằng nó không hơn một chút vô nghĩa mà tôi không thể. Tôi đã nghĩ ra điều kỳ lạ split --filter="cat >file; tar -r ..."
này, nhưng, tốt, nó rất chậm. Và tôi càng đọc về tar
nó dường như vô nghĩa hơn.
Bạn thấy đấy, tar
chỉ là một danh sách các hồ sơ được kết hợp. Các tập tin cấu thành không bị thay đổi theo bất kỳ cách nào - chúng là toàn bộ trong kho lưu trữ. Nhưng chúng bị chặn trên ranh giới khối 512 byte và trước mỗi tệp đều có tiêu đề . Đó là nó. Các định dạng tiêu đề là thực sự, rất đơn giản là tốt.
Vì vậy, tôi đã viết của riêng tôi tar
. Tôi gọi nó là ... shitar
.
z() (IFS=0; printf '%.s\\0' $(printf "%.$(($1-${#2}))d"))
chk() (IFS=${IFS#??}; set -f; set -- $(
printf "$(fmt)" "$n" "$@" '' "$un" "$gn"
); IFS=; a="$*"; printf %06o "$(($(
while printf %d+ "'${a:?}"; do a=${a#?}; done 2>/dev/null
)0))")
fmt() { printf '%s\\'"${1:-n}" %s "${1:+$(z 99 "$n")}%07d" \
%07o %07o %011o %011o "%-${1:-7}s" ' 0' "${1:+$(z 99)}ustar " %s \
"${1:+$(z 31 "$un")}%s"
}
Đó là thịt và khoai tây, thực sự. Nó viết các tiêu đề và tính toán chksum - mà, nói một cách tương đối, là phần khó duy nhất. Nó có ustar
định dạng tiêu đề ... có thể . Ít nhất, nó mô phỏng những gì GNU tar
dường như nghĩ là ustar
định dạng tiêu đề đến điểm mà nó không phàn nàn. Và còn hơn thế nữa, chỉ là tôi chưa thực sự đông máu nó. Ở đây, tôi sẽ chỉ cho bạn:
for f in 1 2; do echo hey > file$f; done
{ tar -cf - file[123]; echo .; } | tr \\0 \\n | grep -b .
0:file1 #filename - first 100 bytes
100:0000644 #octal mode - next 8
108:0001750 #octal uid,
116:0001750 #gid - next 16
124:00000000004 #octal filesize - next 12
136:12401536267 #octal epoch mod time - next 12
148:012235 #chksum - more on this
155: 0 #file type - gnu is weird here - so is shitar
257:ustar #magic string - header type
265:mikeserv #owner
297:mikeserv #group - link name... others shitar doesnt do
512:hey #512-bytes - start of file
1024:file2 #512 more - start of header 2
1124:0000644
1132:0001750
1140:0001750
1148:00000000004
1160:12401536267
1172:012236
1179: 0
1281:ustar
1289:mikeserv
1321:mikeserv
1536:hey
10240:. #default blocking factor 20 * 512
Đó là tar
. Mọi thứ đều được đệm bằng \0
null nên tôi chỉ chuyển em
thành \n
ewlines để dễ đọc. Và shitar
:
#the rest, kind of, calls z(), fmt(), chk() + gets $mdata and blocks w/ dd
for n in file[123]
do d=$n; un=$USER; gn=$(id --group --name)
set -- $(stat --printf "%a\n%u\n%g\n%s\n%Y" "$n")
printf "$(fmt 0)" "$n" "$@" "$(chk "$@")" "$un" "$gn"
printf "$(z $((512-298)) "$gn")"; cat "$d"
printf "$(x=$(($4%512));z $(($4>512?($x>0?$x:512):512-$4)))"
done |
{ dd iflag=fullblock conv=sync bs=10240 2>/dev/null; echo .; } |
tr \\0 \\n | grep -b .
ĐẦU RA
0:file1 #it's the same. I shortened it.
100:0000644 #but the whole first file is here
108:0001750
116:0001750
124:00000000004
136:12401536267
148:012235 #including its checksum
155: 0
257:ustar
265:mikeserv
297:mikeserv
512:hey
1024:file2
...
1172:012236 #and file2s checksum
...
1536:hey
10240:.
Tôi nói loại lên ở đó vì đó không phải là shitar
's mục đích - tar
đã thực hiện điều đó thật đẹp. Tôi chỉ muốn cho thấy nó hoạt động như thế nào - có nghĩa là tôi cần phải chạm vào chksum
. Nếu không, tôi sẽ chỉ dd
lấy phần đầu của tar
tập tin và thực hiện với nó. Điều đó thậm chí có thể hoạt động đôi khi, nhưng nó trở nên lộn xộn khi có nhiều thành viên trong kho lưu trữ. Tuy nhiên, chksum thực sự dễ dàng.
Đầu tiên, làm cho nó có 7 khoảng trắng - (đó là một điều kỳ quặc, tôi nghĩ, như thông số kỹ thuật nói 8, nhưng bất cứ điều gì - một hack là một hack) . Sau đó cộng các giá trị bát phân của mỗi byte trong tiêu đề. Đó là chksum của bạn. Vì vậy, bạn cần siêu dữ liệu tệp trước khi bạn thực hiện tiêu đề hoặc bạn không có chksum. Và đó là một ustar
kho lưu trữ, chủ yếu.
Đồng ý. Bây giờ, những gì nó có nghĩa là để làm:
cd /tmp; mkdir -p mnt
for d in 1 2 3
do fallocate -l $((1024*1024*500)) disk$d
lp=$(sudo losetup -f --show disk$d)
sync
sudo mkfs.vfat -n disk$d "$lp"
sudo mount "$lp" mnt
echo disk$d file$d | sudo tee mnt/file$d
sudo umount mnt
sudo losetup -d "$lp"
done
Điều đó tạo ra ba hình ảnh đĩa 500M, định dạng và gắn kết mỗi cái, và ghi một tệp vào mỗi tệp.
for n in disk[123]
do d=$(sudo losetup -f --show "$n")
un=$USER; gn=$(id --group --name)
set -- $(stat --printf "%a\n%u\n%g\n$(lsblk -bno SIZE "$d")\n%Y" "$n")
printf "$(fmt 0)" "$n" "$@" "$(chk "$@")" "$un" "$gn"
printf "$(z $((512-298)) "$gn")"
sudo cat "$d"
sudo losetup -d "$d"
done |
dd iflag=fullblock conv=sync bs=10240 2>/dev/null |
xz >disks.tar.xz
Lưu ý - rõ ràng các thiết bị khối sẽ luôn luôn chặn chính xác. Khá tiện dụng.
Đó tar
là nội dung của các tệp thiết bị đĩa trong luồng và dẫn đầu ra xz
.
ls -l disk*
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk1
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk2
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk3
-rw-r--r-- 1 mikeserv mikeserv 229796 Sep 3 01:05 disks.tar.xz
Giờ đây, khoảnh khắc của sự thật ...
xz -d <./disks.tar.xz| tar -tvf -
-rw-r--r-- mikeserv/mikeserv 524288000 2014-09-03 01:01 disk1
-rw-r--r-- mikeserv/mikeserv 524288000 2014-09-03 01:01 disk2
-rw-r--r-- mikeserv/mikeserv 524288000 2014-09-03 01:01 disk3
Hoan hô! Khai thác...
xz -d <./disks.tar.xz| tar -xf - --xform='s/[123]/1&/'
ls -l disk*
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk1
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk11
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk12
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk13
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk2
-rw-r--r-- 1 mikeserv mikeserv 524288000 Sep 3 01:01 disk3
-rw-r--r-- 1 mikeserv mikeserv 229796 Sep 3 01:05 disks.tar.xz
So sánh ...
cmp disk1 disk11 && echo yay || echo shite
yay
Và thú cưỡi ...
sudo mount disk13 mnt
cat mnt/*
disk3 file3
Và vì vậy, trong trường hợp này, shitar
thực hiện ok, tôi đoán. Tôi thà không đi sâu vào tất cả những điều mà nó sẽ không làm tốt. Nhưng, tôi sẽ nói - ít nhất đừng làm những dòng mới trong tên tập tin.
Bạn cũng có thể làm - và có lẽ nên, xem xét các lựa chọn thay thế mà tôi đã đưa ra - đây là squashfs
. Bạn không chỉ nhận được kho lưu trữ duy nhất được xây dựng từ luồng - mà còn mount
có thể và được tích hợp vào kernel vfs
:
Từ giả tệp. Ví dụ :
# Copy 10K from the device /dev/sda1 into the file input. Ordinarily
# Mksquashfs given a device, fifo, or named socket will place that special file
# within the Squashfs filesystem, this allows input from these special
# files to be captured and placed in the Squashfs filesystem.
input f 444 root root dd if=/dev/sda1 bs=1024 count=10
# Creating a block or character device examples
# Create a character device "chr_dev" with major:minor 100:1 and
# a block device "blk_dev" with major:minor 200:200, both with root
# uid/gid and a mode of rw-rw-rw.
chr_dev c 666 root root 100 1
blk_dev b 666 0 0 200 200
Bạn cũng có thể sử dụng btrfs (send|receive)
để truyền phát một subvolume vào bất kỳ stdin
máy nén nào có thể sử dụng được mà bạn thích. Subvolume này không cần tồn tại trước khi bạn quyết định sử dụng nó làm thùng chứa nén, tất nhiên.
Tuy nhiên, về squashfs
...
Tôi không tin rằng tôi đang làm công lý này. Đây là một ví dụ rất đơn giản:
cd /tmp; mkdir ./emptydir
mksquashfs ./emptydir /tmp/tmp.sfs -p \
'file f 644 mikeserv mikeserv echo "this is the contents of file"'
Parallel mksquashfs: Using 6 processors
Creating 4.0 filesystem on /tmp/tmp.sfs, block size 131072.
[==================================================================================|] 1/1 100%
Exportable Squashfs 4.0 filesystem, gzip compressed, data block size 131072
compressed data, compressed metadata, compressed fragments,...
###...
###AND SO ON
###...
echo '/tmp/tmp.sfs /tmp/imgmnt squashfs loop,defaults,user 0 0'|
sudo tee -a /etc/fstab >/dev/null
mount ./tmp.sfs
cd ./imgmnt
ls
total 1
-rw-r--r-- 1 mikeserv mikeserv 29 Aug 20 11:34 file
cat file
this is the contents of file
cd ..
umount ./imgmnt
Đó chỉ là -p
đối số nội tuyến cho mksquash
. Bạn có thể nguồn một tệp có -pf
chứa nhiều tệp như bạn muốn. Định dạng rất đơn giản - bạn xác định tên / đường dẫn của tệp mục tiêu trong hệ thống tệp của kho lưu trữ mới, bạn cung cấp cho nó chế độ và chủ sở hữu, sau đó bạn cho nó biết quá trình nào để thực thi và đọc thiết bị xuất chuẩn. Bạn có thể tạo bao nhiêu tùy thích - và bạn có thể sử dụng LZMA, GZIP, LZ4, XZ ... hmm có nhiều ... định dạng nén tùy thích. Và kết quả cuối cùng là một kho lưu trữ mà bạn cd
.
Thêm về định dạng mặc dù:
Tất nhiên, đây không chỉ là một kho lưu trữ - nó là một hình ảnh hệ thống tệp Linux có thể nén, có thể gắn kết. Định dạng của nó là kernel Linux - nó là một hệ thống tập tin được hỗ trợ kernel vanilla. Theo cách này, nó phổ biến như nhân Linux vanilla. Vì vậy, nếu bạn nói với tôi rằng bạn đang chạy một hệ thống Linux vanilla mà tar
chương trình chưa được cài đặt thì tôi sẽ nghi ngờ - nhưng tôi có thể sẽ tin bạn. Nhưng nếu bạn nói với tôi rằng bạn đang chạy một hệ thống vanilla Linux mà squashfs
hệ thống tập tin không được hỗ trợ thì tôi sẽ không tin bạn.