Son zamanlarda bunu yapmak istedim tar
. Bazı soruşturmalar bana yapamayacağımın biraz saçma olduğunu ifade etti. Bu tuhaf split --filter="cat >file; tar -r ..."
şeyi buldum , ama, çok yavaştı. Ve ne kadar tar
çok saçma sapan hakkında o kadar çok okursam görünüyordu.
Gördüğünüz gibi tar
, sadece birleştirilmiş kayıtlar listesi. Kurucu dosyalar hiçbir şekilde değiştirilmez - arşiv içinde tamamen bulunurlar. Ancak 512 baytlık blok sınırlarında engellenir ve her dosyadan önce bir başlık vardır . Bu kadar. Üstbilgi biçimi de gerçekten çok basit.
Ben de kendim yazdım tar
. Ben diyorum ... 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"
}
Gerçekten et ve patates bu. Başlıkları yazar ve nispeten sert olan tek zor kısım olan chksum'u hesaplar. It does ustar
... başlık biçimi belki . En azından, GNU'nun şikayet etmediği noktaya tar
kadar ustar
başlık formatı olduğunu düşünüyor . Ve daha fazlası var, sadece henüz pıhtılaşmamıştım . İşte size göstereceğim:
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
İşte tar
. İle Herşey yastıklı \0
boş değerlere Ben sadece şey öylesine em
içine \n
okunabilmesi için ewlines. Ve 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 .
ÇIKTI
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:.
Orada bir tür diyorum çünkü bu shitar
amaç değil - tar
zaten güzel yapıyor. Sadece nasıl çalıştığını göstermek istedim - yani chksum
. Eğer bu olmasaydı ben sadece dd
bir tar
dosyanın başını kapalı ve onunla yapılır. Bu bazen işe yarayabilir, ancak arşivde birden fazla üye olduğunda dağınık hale gelir. Yine de, chksum gerçekten çok kolay.
İlk olarak, 7 boşluk yapın - (garip bir gnu şey, bence, spesifikasyon 8'in söylediği gibi, ama ne olursa olsun - bir kesmek bir hack'tir) . Ardından, başlıktaki her baytın sekizlik değerlerini toplayın. Bu senin chksum'un. Bu nedenle, üstbilgiyi yapmadan önce dosya meta verilerine ihtiyacınız var veya bir chksum'unuz yok. Ve bu ustar
çoğunlukla bir arşiv.
Tamam. Şimdi ne yapmak gerekiyor:
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
Bu, üç adet 500M disk görüntüsü oluşturur, her birini biçimlendirir ve bağlar ve her birine bir dosya yazar.
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
Not - görünüşe göre engelleme cihazları her zaman doğru şekilde engeller. Oldukça kullanışlı.
Akıştaki tar
disk aygıtı dosyalarının içeriği budur ve çıktıyı yönlendirir 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
Şimdi, gerçek anı ...
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
Yaşasın! Çıkarma...
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
Karşılaştırma ...
cmp disk1 disk11 && echo yay || echo shite
yay
Ve binek ...
sudo mount disk13 mnt
cat mnt/*
disk3 file3
Ve böylece, bu durumda, shitar
tamam, sanırım. Daha doğrusu o şeylerin hepsini girmeyeceğim ediyorum olmaz iyi yapmak. Ama şunu söyleyeceğim - en azından dosya adlarında yeni satırlar yapmayın.
Bu teklif ettiğim alternatifleri göz önünde bulundurarak da yapabilirsiniz - ve belki de yapmalısınız squashfs
. Sadece siz değil akışından inşa tek arşiv alabilirim - ama bu kadar mount
yetenekli çekirdek en ve yerleşik vfs
:
Gönderen sözde file.example :
# 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
Ayrıca btrfs (send|receive)
, hoşunuza giden her stdin
kompresör içine bir alt hacim aktarmak için de kullanabilirsiniz . Elbette sıkıştırma kabı olarak kullanmaya karar vermeden önce bu alt hacmin mevcut olması gerekmez.
Yine de squashfs
...
Bu adaleti yaptığımı sanmıyorum. Çok basit bir örnek:
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
Bu sadece satır içi -p
argüman mksquash
. İstediğiniz kadar dosya -pf
içeren bir dosya kaynağı yapabilirsiniz . Biçim basittir - yeni arşivin dosya sisteminde bir hedef dosyanın adını / yolunu tanımlarsınız, ona bir mod ve bir sahip verirsiniz ve daha sonra stdout'u yürütmek ve okumak için hangi işlemi gerçekleştirirsiniz. İstediğiniz kadar oluşturabilirsiniz - ve LZMA, GZIP, LZ4, XZ ... hmm kullanabilirsiniz ... istediğiniz gibi daha fazla sıkıştırma formatı vardır. Ve sonuç, içine girdiğiniz bir arşivdir cd
.
Biçim hakkında daha fazla bilgi:
Tabii ki bu sadece bir arşiv değil, sıkıştırılmış, monte edilebilir bir Linux dosya sistemi görüntüsüdür. Biçimi Linux çekirdeğidir - vanilya çekirdeği destekli bir dosya sistemidir. Bu şekilde vanilya Linux çekirdeği kadar yaygındır. Bu yüzden, tar
programın kurulu olmadığı bir vanilya Linux sistemi çalıştırdığınızı söylediyseniz , şüpheli olurdum - ama muhtemelen size inanacağım. Ama bana squashfs
dosya sisteminin desteklenmediği bir vanilya Linux sistemi çalıştırdığınızı söylediyseniz, size inanmayacağım.