ブロックデバイスコンテンツを保持するようにtar(など)を説得する方法は?

ブロックデバイスコンテンツを保持するようにtar(など)を説得する方法は?

仮想マシンを一緒にサポートする6つのLinux論理ボリュームがあります。現在、仮想マシンの電源がオフになっているため、一貫した画像を簡単に取得できます。

6つの画像をすべて1つのアーカイブにまとめたいです。簡単に言えば、次のようにすることができます。

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

ただし、これにより当然追加のコピーが作成されます。追加のコピーを避けたいです。

確実な方法は次のとおりです。

tar c /dev/Zia/vm_lvraid_* | whatever

tarは特別なファイル(この場合はシンボリックリンク)を認識し、デフォルトではln -sアーカイブに保存するため、機能しません。または、--dereference直接指すか、/dev/dm-X特別なファイル(デバイスファイル)として認識し、デフォルトでmknodアーカイブに保存します。

この動作を無視するためにtarのコマンドラインオプションを検索しましたが、見つかりませんでした。私もcpio同じ問題を試しましたが、上書きするオプションが見つかりませんでした。私も試してみた7z(同感)。と同じですpax。私も試してみましたが、zip混乱していました。

編集:GNU tarとGNU cpioのソースコードを見ると、どちらもこれを行うことができないようです。少なくとも重大なチートがなければ不可能です(デバイスファイルの特別な処理を無効にすることはできません)。したがって、深刻な欺瞞的な提案や代替ユーティリティを教えていただきありがとうございます。

要約:複数のディスクイメージを一緒に圧縮し(元のデバイスから取得した)、追加のディスクコピーを作成せずに出力をストリーミングできるアーカイブはありますか?私はPOSIXやGNU tarのような一般的な形式の出力を好みます。

ベストアンサー1

tarだから最近書いてみたいです。調査私ができないことを私に示すのは少し面白いです。私はこの奇妙なことを思い出しましたが、split --filter="cat >file; tar -r ..."遅すぎます。読むほど、tarもっと面白く見えました。

ご覧のとおり、tarこれはリンクされたレコードのリストです。構成ファイルはどのように変更されず、アーカイブにそのまま残ります。しかし、彼ら禁止512バイトオフ詰まった境界があり、各ファイルの前にヘッダー。それはすべてです。ヘッダー形式も非常に簡単です。

だから私は自分で書いたtar。私はそれを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"
}

実は肉とじゃがいもです。ヘッダーを作成し、チェックサムを計算します。比較的言えば、これは唯一の難しい部分です。ustarヘッダー書式を実行します...おそらく。少なくともGNUが文句を言わないヘッダファイル形式と見なすことをtarエミュレートします。ustar他にももっとありますが、まだ正しく把握していません。化粧水まだ完了していません。ここでお見せします:

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

それはtar。すべてがnull値で埋められているので、読みやすくするために\0ちょうどewlinesに変換しましたem\nそして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 .

出力

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:.

私は言ったほぼshitarそれは目的ではないので、すでにtar美しく仕上がっています。私はそれがどのように機能するかを見せたいと思いました。つまり、 をタッチする必要があるという意味ですchksum。そうでない場合は、ddファイルヘッダーを削除しtarて操作を完了する必要があります。時にはうまくいくかもしれませんが、プロファイルに複数のメンバーがいると混乱する可能性があります。しかし、chksumは本当に簡単です。

まず7マスにします -(仕様に8と書かれているので、これは奇妙なGNUだと思いますが、何でも - ハッカーはハッカーになります)。その後、ヘッダー内の各バイトの8進値が追加されます。それがあなたのチェックサムです。したがって、ヘッダーを処理する前にファイルメタデータが必要です。それ以外の場合はチェックサムはありません。これはustar主にアーカイブです。

さて、今、その目的は次のとおりです。

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

これにより、500Mディスクイメージを3つ作成し、各イメージをフォーマットしてマウントし、各イメージにファイルを書き込みます。

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

ノート- 明らかに、遮断装置は常に正しく遮断されます。とても便利です。

これはtarストリーム内のディスクデバイスファイルの内容であり、出力を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

今決定的な瞬間..

 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

すごい!抽出成功..

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

比較する...

cmp disk1 disk11 && echo yay || echo shite
yay

そしてマウント...

sudo mount disk13 mnt
cat mnt/*
disk3 file3

だから今回の場合はshitar性能が悪くなかったようです。私は彼に関連するすべてを議論したくないに慣れるよかったです。しかし、私は少なくともファイル名に改行文字を追加しないように言いたいと思います。

あなたもこれを行うことができます。おそらく私が提供した代替案を検討する必要があります。これはsquashfsストリームから構築された単一のアーカイブを得るだけでなく、しかしそれはmountできます。カーネルに組み込みvfs

~から擬似ファイル:

# 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

また、使用することができますbtrfs (send|receive)stdin希望の圧縮可能なコンプレッサーにサブボリュームをストリーミングします。もちろん、圧縮コンテナとして使用することを決定する前に、このサブボリュームが存在する必要はありません。

それでも約squashfs...

私は私がそれを定義していると信じていません。以下は非常に簡単な例です。

 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

これは単に-pインラインパラメータですmksquash-pf必要な数のファイルを含むソースファイルを取得できます。フォーマットは簡単です。新しいアーカイブのファイルシステムでターゲットファイルの名前/パスを定義し、モードと所有者を指定して実行し、標準出力を読み取るプロセスを指定します。好きなだけ多く作成できます。 LZMA、GZIP、LZ4、XZを使用できます。必要に応じてより多くの圧縮形式があります。最終結果はにドロップできるアーカイブですcd

フォーマットに関する追加情報:

もちろんそうではありませんただアーカイブ - 圧縮されマウント可能な Linux ファイルシステムイメージです。フォーマットはLinuxカーネルです。これは一般的なカーネルサポートファイルシステムです。このように、通常のLinuxカーネルと同じくらい一般的です。したがって、このプログラムがインストールされていない基本的なLinuxシステムを実行していると言うと、tar私は懐疑的です。しかし、おそらくあなたを信じるでしょう。しかし、あなたがファイルシステムをサポートせずにバニラLinuxシステムを実行していると言うなら、squashfs私はあなたの言葉を信じていません。

おすすめ記事