내에 4GB 파일 abc
이 있다고 가정 해 보겠습니다. 로컬 컴퓨터입니다. SFTP를 통해 원격 서버에 업로드했는데 몇 시간이 걸렸습니다.
이제 파일을 약간 수정했습니다 (최대 50MB이지만이 파일의 연속 바이트는 아님). abc2
에 저장했습니다. 또한 로컬 컴퓨터에 원본 파일 abc
도 보관했습니다.
abc
및 abc2
의 이진 차이를 계산하는 방법은 무엇입니까?
애플리케이션 :
-
patch
파일 (최대 100MB) 만 보낼 수 있습니다. 전체abc2
파일을 다시 업로드하는 대신 (몇 시간이 다시 소요됩니다!) 원격 서버에서abc2
를 다시 만듭니다.abc
및patch
의 서버에만 해당됩니다. -
abc
및abc2
백업에 8GB를 낭비하는 대신 로컬에서abc
+patch
, 따라서 < 4100MB 만 필요합니다.
어떻게해야합니까?
PS : 텍스트의 경우 diff
를 알고 있지만 여기서는 모든 원시 바이너리 형식에 대해 작동 할 수있는 것, zip 파일, 실행 파일 또는 다른 유형의 파일 일 수 있습니다.
PS2 : 가능하면 ; 두 컴퓨터간에 변경 사항을 효율적으로 복제 할 수 있다는 것을 알고 있지만 (변경되지 않은 데이터를 재전송하지 않음) 여기서는 나중에 재현 할 수있는 patch
파일을 원합니다. abc
와 patch
가 모두 있습니다.
답변
두 번째 응용 프로그램 / 문제의 경우 시도하는 대신 restic
또는 borgbackup
와 같은 중복 제거 백업 프로그램을 사용합니다. “패치”또는 차이점을 수동으로 추적합니다. restic
백업 프로그램을 사용하면 여러 머신의 디렉토리를 동일한 백업 저장소로 백업하여 개별 머신의 파일 조각과 머신간에 백업 데이터를 중복 제거 할 수 있습니다. (borgbackup
에 대한 사용자 경험이 없으므로 해당 프로그램에 대해 아무 말도 할 수 없습니다.)
abc
및 abc2
파일은 rsync
로 수행 할 수 있습니다.
예 : abc
및 abc2
는 153MB입니다. abc2
파일은 다른 데이터와 함께 파일의 처음 2.3MB :
$ ls -lh total 626208 -rw-r--r-- 1 kk wheel 153M Feb 3 16:55 abc -rw-r--r-- 1 kk wheel 153M Feb 3 17:02 abc2
abc
를 abc2
로 변환하고 이름을 abc-diff
로 지정하기위한 패치 :
$ rsync --only-write-batch=abc-diff abc2 abc
$ ls -lh total 631026 -rw-r--r-- 1 kk wheel 153M Feb 3 16:55 abc -rw------- 1 kk wheel 2.3M Feb 3 17:03 abc-diff -rwx------ 1 kk wheel 38B Feb 3 17:03 abc-diff.sh -rw-r--r-- 1 kk wheel 153M Feb 3 17:02 abc2
생성 된 파일 abc-diff
는 실제 diff ( “패치 파일”)이고 abc-diff.sh
는rsync
가 생성하는 짧은 셸 스크립트 :
$ cat abc-diff.sh rsync --read-batch=abc-diff ${1:-abc}
이 스크립트는 iv id = “f91b090ab2 파일이 주어지면 abc
를 abc2
와 동일하게 수정합니다. “>
:
$ md5sum abc abc2 be00efe0a7a7d3b793e70e466cbc53c6 abc 3decbde2d3a87f3d954ccee9d60f249b abc2 $ sh abc-diff.sh $ md5sum abc abc2 3decbde2d3a87f3d954ccee9d60f249b abc 3decbde2d3a87f3d954ccee9d60f249b abc2
파일 abc-diff
는 이제 abc
가있는 다른 곳으로 이전 될 수 있습니다. rsync --read-batch=abc-diff abc
명령을 사용하여 패치를 abc
파일에 적용하여 해당 내용을 abc2
파일입니다.
패치를 다시 적용하는 것이 안전 해 보입니다. 오류 메시지도없고 파일 내용도 변경되지 않습니다 (MD5 체크섬은 변경되지 않음).
명시적인 “역 패치”를 생성하지 않는 한 응용 프로그램을 쉽게 실행 취소 할 수있는 방법이 없습니다.
또한 2.3MB 수정을 abc2
데이터의 다른 위치에 기록하는 것을 테스트했습니다. 생성 된 “패치”의 크기는 4.6MB로 수정 된 비트 만 패치에 저장되었음을 나타냅니다.
댓글
답변
abc와 abc2의 이진 차이를 계산하는 방법
bsdiff / bspatch 또는 xdelta 및 기타 사용
$ bsdiff older newer patch.bin # patch.bin is created [...] $ bspatch older newer patch.bin # newer is created
그러나 man 페이지의 다음 권고 사항에 유의해야합니다.
-
bsdiff
는 크기의 17 배에 해당하는 메모리를 사용합니다. oldfile , oldfile 크기의 8 배인 절대 최소 작업 세트 크기가 필요합니다. -
bspatch
은 oldfile 크기에 newfile 크기를 더한 것과 동일한 메모리를 사용하지만 성능 저하없이 매우 작은 작업 집합을 허용 할 수 있습니다.
댓글
- 예를 보여 주시겠습니까?
- 답변 해 주셔서 감사합니다.
bsdiff uses memory equal to 17 times the size of oldfile
따라서이 방식은 ‘ 일반적으로 4GB 파일 (최소한 내 8GB RAM 시스템)에서는 작동하지 않습니다. - @Basj 가능한 것은 4GB 파일을 더 작은 파일 (예 : 각각 128MB)로 자르고 개별 델타를 수행하는 것입니다. 이것은 스크립트로 래핑 될 수 있습니다. chopped-bsdiff : 파일을 자르고, bsdiff를 쌍으로 수행하고, 파일을 아카이브로 tar합니다. chopped-bspatch : 아카이브에서 쌍별 패치를 읽고, 입력 파일 청크에 적용하고, 출력을 분류합니다.
- @Kaz 알지만 ‘ 더 많이 찾고 있습니다. 크기에 관계없이 한 줄 (
mydiff abc abc2 > patchfile
및mypatch abc patchfile > abc3
)로 호출 할 수있는 바로 사용할 수있는 도구입니다. 또한 128MB 청크로 자르면abc
의 처음 1GB ==abc2
의 마지막 (후행) 1GB이면 어떻게됩니까? ? ‘abc-first128mb
를abc2-first128mb
와 비교할 때 일치하는 항목이 없으므로 효율적이지 않을 수 있습니까?
답변
강제 diff
: 파일을 텍스트로 처리 :
diff -ua abc abc2
여기 에 설명 된대로.
-
-u
통합 컨텍스트의 NUM (기본값 3) 줄 출력 -
-a
모든 파일을 텍스트로 처리
이렇게하면 패치를받을 수 있습니다. 단점은 “줄”이 상당히 길 수 있고 패치를 부 풀릴 수 있다는 것입니다.
댓글
- 이런, 그렇습니다. ‘ 실제로
n
를 원하지 않습니다. ‘이 작동하는지 알고 싶습니다. ‘ ” 라인 “이됩니다. - 댓글 감사합니다! 두 개의 매우 유사한 256MB 파일
abc
및abc2
를 만들었습니다. 그런 다음diff -ua abc abc2 > patch
를 시도한 다음abc
를abc3
에 복사하고 복구를 시도했습니다. abc3 및patch
덕분에 div id = “969241e5c0”>
:patch abc3 < patch
그러나 작동하지 않았습니다. 마지막에abc3
는 256MB 대신 1KB였습니다. 아시나요?
0x0a
, 즉 개행이 없거나 매우 적 으면 ‘ 잘 작동하지 않습니다. 테스트 해 보면 흥미로울 것입니다. wc -l
를 사용하여 바이너리에 대해 교육적인 추측을 할 수 있습니다. 임의의 바이너리에서 꽤 잘 작동 할 것으로 예상합니다. 예를 들어 내 컴퓨터에서 120 만 개의 ” 라인 “과 59M 는 약 230k이므로 평균 ” 라인 “은 각각 220 바이트 및 258 바이트 미만입니다. ‘이 파일이 다른 파일과 다른 이유는 알 수 없지만 분명히 운이 좋지 않을 수 있습니다. 실제로 나는 그것이 꽤 잘 작동 할 것이라고 생각하며 그렇지 않다면 여전히 ‘ 여전히 재미있는 해킹입니다. 답변
xdelta 를 사용합니다.이 유형의 용도를 위해 만들어졌습니다. 최신 버전의 VCDIFF (RFC 3284)를 기반으로합니다.
댓글
- 링크가 작동하지 않습니다 (다른 URL이 있습니까?). 1) diff
patch
파일을 계산하고 2)abc2
를 복원하는 방법을 보여주기 위해 몇 줄에 예제를 추가 할 수도 있습니다. ,abc
및patch
만 주어 졌습니까? - 고정 URL
- @vonbrand에게 감사드립니다. . 그러한 예가 있습니까?
답변
내 테스트에 따른 다른 답변 보완 :
diff
두 개의 매우 유사한 256MB 파일 abc
및 . 그런 다음 diff 파일을 만들어 보겠습니다.
diff -ua abc abc2 > abc-abc2.diff
이제 abc2
를 복구 해 보겠습니다. 원본 abc
파일 및 abc-abc2.diff
:
cp abc abc3 patch abc3 < abc-abc2.diff
또는
cp abc abc3 patch abc3 -i abc-abc2.diff
또는
patch abc -i abc-abc2.diff -o abc3
Linux에서 작동합니다. Windows에서도 시도했지만 (patch.exe 및 diff.exe도 사용할 수 있음) 알 수없는 이유로 실패했습니다. 생성 된 abc3
파일은 256MB 대신 1KB에 불과합니다 (I ” 이 답변은 나중에 여기에서 업데이트합니다).
rsync
허용 된 답변에 자세히 설명 된대로 다음과 같이 작동합니다.
rsync --only-write-batch=abc-abc2-diff abc2 abc cp abc abc3 rsync --read-batch=abc-abc2-diff abc3
rdiff
에 자세히 설명 됨 답변 , 이것도 해결책입니다.
rdiff signature abc abc-signature rdiff delta abc-signature abc2 abc-abc2-delta rdiff patch abc abc-abc2-delta abc3
여기 에서 작동합니다.
댓글
- ‘ CONTROL을 만나면 파일 끝을 알리는 ” 텍스트 ” 모드에서 입력 파일을 읽고 있었기 때문에 Windows에서 패치가 실패했습니다. 입력 파일의 -Z (바이트 0x18). 이것은 디렉토리에 길이가 기록되지 않았던 초기 DOS 시대의 레거시 모드입니다. 파일 길이는 512 바이트 섹터 수를 기반으로 계산되었습니다. 바이너리 모드에서 파일을 열도록
patch
에 지시 할 수 있다면 ‘이 오류가 없어야합니다.
rsync --read-batch=abc-diff ${1:-abc}
(자동으로 생성 된 .sh 스크립트)가remote destination is not allowed with --read-batch
rsync error: syntax or usage error (code 1) at main.c(1326) [Receiver=3.1.2]
그러나rsync --read-batch=abc-diff abc
는 성공적으로 작동했습니다.이 두 가지 유사한 명령의 차이점은 무엇입니까?abc
를 입력으로 받아들이고 패치를 적용하는 방법이 있습니까?diff-abc
--read-batch
를 사용하지만abc
” 현재 위치 ” 대신 새 파일abc3
로 출력 하시겠습니까? (가능한 경우 파이프없이rsync
를 사용하여 모두 Linux 및rsync.exe
를 사용할 수있는 Windows에서도 쉽게 작동하도록합니다.)$1
에 값이 있으면 명령이 다른 작업을 수행합니다.${1:-abc}
는 ” 첫 번째 위치 매개 변수 ($1
)를 사용함을 의미합니다. ‘이 비어 있거나 정의되지 않았습니다. 비어 있거나 정의되지 않은 경우 ‘ 대신abc
를 ” 사용하세요. 저는 ‘$1
시도했을 때 값이 있다 라고 가정합니다. 원격 대상 주소입니다.${1:-abc}
에 대한 답변을 주셔서 감사합니다. Windows에서 시도했기 때문에 실패했을 수 있습니다 (‘ 원격 서버용 Linux와 Windows 로컬에서 모두 rsync를 사용하고 있습니다). 하지만 ‘rsync --read-batch=abc-diff abc
가 작동하므로 완벽합니다. 🙂