깊고 복잡한 디렉토리 구조를 수정할 수 있습니다. 파일을 이동(접두사 변경)할 수 있고 파일 내용을 부분적으로 변경할 수 있습니다.
네트워크를 통해 전송되는 데이터의 양을 줄이고 싶습니다.
rsync
4k 크기의 블록에서 작동합니다(제 기억이 맞다면).
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