Katranı (vb.) Blok cihaz içeriğini arşivlemeye nasıl ikna edebilirim?


13

Birlikte bir sanal makineyi destekleyen altı Linux mantıksal birimim var. VM şu anda kapanıyor, bu yüzden tutarlı görüntüler almak kolaydır.

Altı görüntünün tümünü bir arşivde bir araya getirmek istiyorum. Önemsiz, böyle bir şey yapabilirdim:

cp /dev/Zia/vm_lvraid_* /tmp/somedir
tar c /tmp/somedir | whatever

Ancak bu elbette fazladan bir kopya oluşturur. Fazladan kopyadan kaçınmak istiyorum.

Bariz yaklaşım:

tar c /dev/Zia/vm_lvraid_* | whatever

tar, dosyaları özel olarak tanıdığından (bu durumda sembolik bağlantılar) ve temelde ln -sarşivi depolar . Veya --dereferencedoğrudan veya doğrudan işaret ederek /dev/dm-Xbunları özel (aygıt dosyaları) olarak tanır ve temelde mknodarşivde saklar .

Bu davranışı geçersiz kılmak için katran komut satırı seçenekleri aradım ve bulamadım. Ben de denedim cpio, aynı sorun, ve orada da geçersiz kılmak için herhangi bir seçenek bulamadı. Ben de denedim 7z(aynen). İle aynı pax. Ben bile denedim zip, ki bu sadece karıştı.

edit: GNU katranı ve GNU cpio kaynak koduna bakıldığında, bunların hiçbiri bunu yapabilir. En azından ciddi hile yapmadan değil (cihaz dosyalarının özel kullanımı devre dışı bırakılamaz). Bu nedenle, ciddi hile önerileri takdir edilecektir veya alternatif araçlar.

TLDR: Birden fazla disk görüntüsünü bir araya toplayan (ham aygıtlardan alınan) ve bu disk üzerinde fazladan disk kopyaları çıkarmadan akış sağlayan bazı arşivleyiciler var mı? Benim tercihim POSIX veya GNU tar gibi ortak bir formatta çıktı olurdu.


İkna ettim.
mikeserv

Yanıtlar:


11

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 tarkadar ustarbaş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ı \0boş değerlere Ben sadece şey öylesine emiçine \nokunabilmesi 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 shitaramaç değil - tarzaten güzel yapıyor. Sadece nasıl çalıştığını göstermek istedim - yani chksum. Eğer bu olmasaydı ben sadece ddbir tardosyanı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 tardisk 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, shitartamam, 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 mountyetenekli ç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 stdinkompresö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 -pargüman mksquash. İstediğiniz kadar dosya -pfiç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, tarprogramın kurulu olmadığı bir vanilya Linux sistemi çalıştırdığınızı söylediyseniz , şüpheli olurdum - ama muhtemelen size inanacağım. Ama bana squashfsdosya sisteminin desteklenmediği bir vanilya Linux sistemi çalıştırdığınızı söylediyseniz, size inanmayacağım.


Mike, insanların deney yapabilmesi için kendine yeten küçük bir örnek oluşturmana engel olabilir miyiz? Yukarıdakilerin en azından bir kısmını yapıyor olabilirsiniz, ama emin değilim. Gelen input f 444 root root dd if=/dev/sda1 bs=1024 count=10dosya girişi f nedir? Belki bir oyuncak cihaz oluşturmak, veriyle doldurmak ve ondan yazmak daha iyi olur? Ve tüm bunlar kök gerektirir mi?
Faheem Mitha

@FaheemMitha - evet bunu yapabilirim, ama burada yapmadım. Bağlantı resmi belgelere - doğrudan ondan alınır. Yine de bir komut örneği yapsaydım daha iyi olur. Daha önce yaptım - oldukça havalı. Her neyse - inputdosya squashfsarşivdeki bir dosyadır - komutu çalıştırmaktan kaynaklanan dosya sistemi görüntüsü. Bunu yaptığınızda mksquash, çalıştırılan ve stdoutsıkıştırma zamanında yakalanan komutlar için bu sözde komutları belirtebilirsiniz .
mikeserv

@FaheemMitha - oh, ve sıkıştırma yapmak için kök gerektirmez , ancak montajı yapabilir - sonuç veren bir dosya sistemi görüntüsüdür. Tüm Linux Live disklerinin kullandığı dosya sistemi ile aynıdır. Aslında - çok güzel bir şey - cihaz dosyalarınızı ve keyfi MAJ: MIN numaralarını ayarlamak gibi, kök olmadan bu sahte dosyaları kullanarak kök sahipli bir görüntü oluşturabilmenizdir.
mikeserv

Sanırım bir cihaz dosyası oluşturmak, ona yazmak ve daha sonra hiç monte etmeden mümkün olmalı, değil mi? Yani, belki de açıkça tercih edilecek olan kök gerektirmez.
Faheem Mitha

Burada hiçbir btrfs yok, bu yüzden işe yaramaz. Ama squashfs işe yarayacak kadar çılgın. Her ne kadar ortak bir arşiv formatı olmamasının dezavantajı var.
derobert

4

Sorun bir süredir beni şaşırttı ve bence işe yarayacak bir çözüm buldum.

-si{NAME}Bayrağı kullanarak 7z ile istediğinizi elde edebileceğinizi düşünüyorum .

İhtiyacınıza uyum sağlayabileceksiniz.

7z a test.7z -siSDA2.txt < /dev/sda1
7z a test.7z -siSDA2.txt < /dev/sda2

7z l test.7z 

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,8 CPUs)

Listing archive: test.7z

--
Path = test.7z
Type = 7z
Method = LZMA
Solid = -
Blocks = 2
Physical Size = 1770
Headers Size = 162

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2014-08-19 22:01:08 .....         6314          804  SDA1.txt
2014-08-19 22:01:11 .....         6314          804  SDA2.txt
------------------- ----- ------------ ------------  ------------------------
                                 12628         1608  2 files, 0 folders

EDIT : kedinin yararsız kullanımını kaldırmak


İnsanların deneyebileceği küçük bir örneğe sahip olmak yardımcı olacaktır. Örneğin, bir blok cihazı oluşturun, ona yazın, sonra ondan yazın. Kök gerektirmeyen bir artı olacaktır.
Faheem Mitha

Örnekte / dev / sda1 bir blok cihazıdır. Cat komutu, cihazın içeriğini stdout'a boşaltmaktır. 7z sonra arşivi oluşturur (veya günceller) ve verileri stdin'den -si parametresi ile belirtilen dosya adında saklar. Arşivdeki sonuç, her blok cihazının içeriğidir. "Cat" komutu, verileri cihazdan okumak için root'a ihtiyaç duyar.
Tony

Bu, Yararsız bir Kedi Kullanımıdır , ancak aksi takdirde faturaya oldukça iyi uymaktadır. Garip bir şekilde benim sayfam 7z-si bir dosya adı alabilir bahsetmiyor, ama işe yarıyor. Mükemmel değil (çıktı bir yere pipo edilemez), ancak şimdiye kadar ortak bir formatta çıktı veren kesinlikle en iyisidir.
derobert

@FaheemMitha root gerektiren veya olmayan sisteminizdeki izin ayarlarına bağlı olacaktır, ancak sadece root yeni blok cihazları oluşturabilir.
derobert

@derobert Kediyi Kaldırdı :)
Tony
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.