tar 디렉토리는 수정된 파일 블록만 보냅니다.

tar 디렉토리는 수정된 파일 블록만 보냅니다.

깊고 복잡한 디렉토리 구조를 수정할 수 있습니다. 파일을 이동(접두사 변경)할 수 있고 파일 내용을 부분적으로 변경할 수 있습니다.

네트워크를 통해 전송되는 데이터의 양을 줄이고 싶습니다.

rsync4k 크기의 블록에서 작동합니다(제 기억이 맞다면).

tar파일 시스템 구조 및 속성에 대한 메타 정보를 보존하고 각 다음 파일의 여러 4KB 오프셋에서 파일 내용을 시작하여 rsync알고리즘 이점을 얻기 위해 일종의 연결(유사한 것)을 사용할 수 있습니까 ?

내가 해결하고 싶은 문제는 누락입니다 rsync. 파일 내용이 변경되었는지, 파일이 동기화 간에 동시에 이동되었는지를 감지하여 데이터 전송을 줄이기 위해 대상 파일의 일치하는 블록을 사용하는지 여부를 감지할 수 없습니다.

답변1

의견에 있는 귀하의 제안(실제로 귀하의 질문에 있어야 함)에 따르면 이것이 귀하가 원하는 것 같습니다.

cd /path/to/directory
tar cf /var/tmp/directory.tar .
rsync -azv /var/tmp/directory.tar remote:/var/tmp/directory.tar
ssh remote 'cd /path/to/destination && tar xf /var/tmp/directory.tar'

directory.tar수납을 위해서는 양쪽에 충분한 공간이 있어야 합니다.


tar 파일의 시작 부분에 소량의 콘텐츠(예: 단일 바이트)를 추가(또는 제거)하면 사소해 보이는 이 솔루션이 작동할 것인지 질문을 받았습니다.

이 예가 rsync이와 같은 상황을 얼마나 능숙하게 처리할 수 있는지 보여주기를 바랍니다. 이는 원격 서버에 대한 동등한(인증서 키) 로그인이 있는 경우 가장 잘 작동하므로 비밀번호를 입력하는 데 시간을 소비할 필요가 없습니다.

# Generate some data
dd iflag=fullblock bs=1M count=200 </dev/urandom >200M.dat

# See how long it takes to transfer
time rsync -av 200M.dat remote:

# See how long it takes to transfer "nothing"
time rsync -av 200M.dat remote:

# Generate one byte of data and prepend it to another data file
dd bs=1 count=1 </dev/urandom >1b.dat
cat 1b.dat 200M.dat >200M1b.dat

# Copy the new file across to the original target
time rsync -av 200M1b.dat remote:200M.dat

# Clean up
rm 1b.dat 200M.dat 200M1b.dat
ssh remote rm 200M.dat

알고리즘이 데이터 스트림 시작 부분에 삽입된 단일 바이트를 처리할 수 있는 경우 전송에는 몇 분 밖에 걸리지 않습니다. 그렇지 않은 경우 전송 시간은 처음과 거의 비슷할 것으로 예상할 수 있습니다.

답변2

여기 또 다른 팁이 있습니다. 이것hrsync도구GitHub에서 찾은 내용은 파일 이름을 바꾸거나 소스 트리의 디렉터리 간에 파일을 이동할 때 파일에 대한 메모리를 유지하는 데 매우 좋은 것 같습니다.

  • 소스 트리에서 파일의 이동 및 편집을 추적할 수 있습니다.
  • 이는 쉘 스크립트이며 소스 시스템에 설치하는 데 관리 권한이 필요하지 /usr/local/bin않지만
  • 로컬 및 원격 시스템 모두에 하드 링크를 처리할 수 있는 파일 시스템이 있어야 합니다.
  • 이름이 바뀌는 파일의 변경 사항을 추적할 수 없습니다.교체됨(즉, 제자리에서 편집하는 대신 삭제하고 다시 생성)

hrsync /path/to/directory/ remote:/path/to/destination/

답변3

bash명령줄 유틸리티만 사용하여 솔루션을 찾았습니다. 솔루션을 최적화할 수 있습니다. 파일을 크기의 오름차순으로 정렬하고 각 블록에 가능한 한 많은 작은 파일을 넣습니다(여기서는 배낭 문제 =). 그러나 이는 과도한 엔지니어링이 됩니다.

pack.bash:

#! /usr/bin/env bash

set -e

[[ -d "$1" ]]
[[ -d "$( dirname '$2' )" ]]

BLOB="$2.blob"
FSIZES="$2.sizes"
OFFSET=0

shopt -s globstar
for f in "$1"/* "$1"/**/*
do
    if [[ -f "$f" ]]
    then
        SIZE=$( stat -c %s "$f" )
        echo "$SIZE" >> "$FSIZES"
        COUNT=$(( ($SIZE + 4096 - 1) / 4096 ))
        dd if="$f" of="$BLOB" bs=4096 seek=$OFFSET count=$COUNT conv=notrunc
        OFFSET=$(( $COUNT + $OFFSET ))
    fi
done

cp --recursive --archive --attributes-only "$1" "$2.dir"
XZ_OPT="-9e --threads=$(( $( nproc ) + 1 ))" tar cpJf "$2.tar.xz" -C "$2.dir" .
rm --recursive "$2.dir"

unpack.bash:

#! /usr/bin/env bash

set -e

BLOB="$2.blob"
FSIZES="$2.sizes"

[[ -f "$BLOB" ]]
[[ -f "$FSIZES" ]]

mkdir --parents "$1"
[[ ! "$( ls -A '$1' )" ]]

tar xpJf "$2.tar.xz" -C "$1"

SIZES=($( < "$FSIZES" ))

i=0
OFFSET=0
shopt -s globstar
for f in "$1"/* "$1"/**/*
do
    if [[ -f "$f" ]]
    then
        SIZE=${SIZES[i]}
        dd if="$BLOB" of="$f" bs=4096 skip=$OFFSET count=$SIZE iflag=count_bytes
        OFFSET=$(( $OFFSET + ($SIZE + 4096 - 1) / 4096 ))
        i=$(( $i + 1 ))
    fi
done

관련 정보