Jadi baru-baru ini saya ingin melakukan ini tar
. Beberapa investigasi menunjukkan kepada saya bahwa saya tidak bisa melakukannya. Aku memang menemukan hal aneh ini split --filter="cat >file; tar -r ..."
, tapi, yah, itu sangat lambat. Dan semakin saya membaca tentang tar
semakin tidak masuk akal rasanya.
Anda lihat, tar
ini hanya daftar catatan yang digabungkan. File konstituen tidak diubah dengan cara apa pun - mereka utuh dalam arsip. Tapi mereka diblokir pada batas blok 512-byte , dan sebelum setiap file ada header . Itu dia. Format tajuk juga sangat, sangat sederhana.
Jadi, saya menulis sendiri tar
. Saya menyebutnya ... 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"
}
Itu daging dan kentang, sungguh. Ini menulis header dan menghitung chksum - yang, secara relatif, adalah satu-satunya bagian yang sulit. Itu ustar
format header ... mungkin . Paling tidak, ia meniru apa yang tar
tampaknya GNU anggap ustar
format tajuk ke titik yang tidak dikeluhkan. Dan ada lebih dari itu, hanya saja saya belum benar-benar menggumpalnya . Di sini, saya akan menunjukkan kepada Anda:
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
Itu tar
. Semuanya diisi dengan \0
nol jadi saya hanya berubah em
menjadi \n
ewlines untuk dibaca. Dan 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 .
KELUARAN
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:.
Saya katakan agak di atas sana karena itu bukan shitar
tujuan - tar
sudah melakukannya dengan indah. Saya hanya ingin menunjukkan cara kerjanya - yang berarti saya perlu menyentuh chksum
. Kalau bukan karena itu saya hanya akan dd
mengambil kepala tar
file dan selesai dengan itu. Itu bahkan kadang-kadang bisa berfungsi, tetapi akan berantakan ketika ada banyak anggota dalam arsip. Tetap saja, chksum sangat mudah.
Pertama, buat 7 spasi - (yang merupakan hal aneh gnu, saya pikir, seperti yang dikatakan spek 8, tapi apa pun - peretasan adalah peretasan) . Kemudian tambahkan nilai oktal dari setiap byte di header. Itu chksum Anda. Jadi Anda perlu metadata file sebelum Anda melakukan header, atau Anda tidak memiliki chksum. Dan itu ustar
sebagian besar arsip.
Baik. Sekarang, apa yang harus dilakukan:
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
Itu membuat tiga gambar disk 500 juta, masing-masing format dan mount, dan menulis file untuk masing-masing.
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
Catatan - tampaknya memblokir perangkat hanya akan selalu memblokir dengan benar. Cukup berguna.
Itulah tar
isi file perangkat disk yang di-stream dan mengirim output ke pip 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
Sekarang, momen kebenaran ...
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
Hore! Ekstraksi ...
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
Perbandingan...
cmp disk1 disk11 && echo yay || echo shite
yay
Dan gunung ...
sudo mount disk13 mnt
cat mnt/*
disk3 file3
Jadi, dalam hal ini, shitar
berkinerja baik, kurasa. Saya lebih suka tidak membahas semua hal yang tidak akan berhasil dengan baik. Tapi, saya akan mengatakan - jangan lakukan baris baru di nama file setidaknya.
Anda juga dapat melakukan - dan mungkin harus, mempertimbangkan alternatif yang saya tawarkan -ini squashfs
. Anda tidak hanya mendapatkan arsip tunggal yang dibangun dari aliran - tetapi juga mount
dapat dan dibangun di dalam kernel vfs
:
Dari pseudo-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
Anda juga dapat menggunakan btrfs (send|receive)
untuk mengalirkan subvolume ke dalam stdin
kompresor apa pun yang Anda inginkan. Subvolume ini tidak perlu ada sebelum Anda memutuskan untuk menggunakannya sebagai wadah kompresi, tentu saja.
Namun, tentang squashfs
...
Saya tidak percaya saya melakukan keadilan ini. Berikut ini contoh yang sangat sederhana:
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
Itu hanya -p
argumen inline untuk mksquash
. Anda dapat sumber file dengan yang -pf
mengandung sebanyak yang Anda suka. Formatnya sederhana - Anda menentukan nama / jalur file target di sistem file arsip baru, Anda memberikannya mode dan pemilik, dan kemudian Anda memberi tahu proses untuk mengeksekusi dan membaca stdout dari. Anda dapat membuat sebanyak yang Anda suka - dan Anda dapat menggunakan LZMA, GZIP, LZ4, XZ ... hmm ada lebih banyak ... format kompresi yang Anda inginkan. Dan hasil akhirnya adalah arsip tempat Anda cd
.
Lebih lanjut tentang format:
Ini, tentu saja, bukan hanya arsip - ini adalah citra sistem file Linux yang dapat dimounting. Formatnya adalah kernel Linux - itu adalah sistem file yang didukung oleh vanilla kernel. Dengan cara ini, ini sama dengan kernel vanilla Linux. Jadi jika Anda mengatakan kepada saya Anda menjalankan sistem Linux vanilla di mana tar
program tidak diinstal saya akan meragukan - tapi saya mungkin akan percaya Anda. Tetapi jika Anda mengatakan kepada saya Anda menjalankan sistem Linux vanilla di mana squashfs
filesystem tidak didukung saya tidak akan percaya Anda.