가상 머신을 함께 지원하는 6개의 Linux 논리 볼륨이 있습니다. 현재 가상 머신의 전원이 꺼져 있으므로 일관된 이미지를 쉽게 얻을 수 있습니다.
6개의 이미지를 모두 하나의 아카이브로 묶고 싶습니다. 간단히 말해서 다음과 같이 할 수 있습니다.
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
나는 회의적일 것입니다. 그러나 아마도 당신을 믿을 것입니다. 하지만 당신이 파일 시스템 지원 없이 바닐라 리눅스 시스템을 운영하고 있다고 말한다면 squashfs
나는 당신의 말을 믿지 않을 것입니다.
답변2
귀하의 문제는 한동안 저를 괴롭혔으며 효과적인 해결책을 찾은 것 같습니다.
나는 당신이 원하는 것을 달성하기 위해 7z 플래그를 사용할 수 있다고 생각합니다 -si{NAME}
.
귀하의 필요에 맞게 조정할 수 있습니다.
7z a test.7z -siSDA1.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
편집하다: 쓸데없는 고양이 사용을 제거하십시오.
답변3
tar가 이 작업을 수행하는지 여부에 관심이 없고 블록 장치 콘텐츠의 아카이브만 원하는 경우 장치의 바이너리 이미지를 선택한 파일 이름으로 생성하는 ddrescue를 사용할 수 있습니다. 설치 프로그램(Debian용)은 gddrescue라고 합니다.
이미지를 생성한 후에는 이미지 작성기를 사용하여 이미지를 복원하거나 이미지를 마운트하여 내용을 보고 복사할 수도 있습니다.