update2: 심심하지만 두 번째 해결책을 설명하겠습니다.

update2: 심심하지만 두 번째 해결책을 설명하겠습니다.

폴더 A를 폴더 B로 동기화하고 싶지만 다음과 같은 제한 사항이 있습니다.

  • 폴더 A에는 수백 개의 폴더에 수천 개의 파일과 수백 기가바이트의 파일이 포함되어 있습니다.

  • 폴더 B에는 폴더 A(및 필요한 모든 폴더)에 최신 10GB(또는 기타) 파일이 포함되어 폴더 A에 있는 최신 파일의 파일 및 구조를 복제합니다.

  • 동기화가 실행될 때마다 폴더 B는 폴더 A의 최신 10GB 파일로 제한되고 오래된 파일은 삭제됩니다.

  • 빈 디렉토리는 정리해야 하지만 필요한 경우 직접 정리할 수 있습니다.

bash나 OS X에서 실행되는 더 나은 도구가 있다면 rsync를 통해 이 작업을 수행할 필요는 없지만 로그인 세션 없이 독립형으로 실행할 수 있어야 합니다.

답변1

#비추천인 경우 댓글로 이유를 적어주세요. 정말 나쁘다!

내 의견에서 해결책을 찾았습니다.

전체 명령줄은 다음과 같습니다. $ find . -type f -printf "%T@ %p %s\n"| sort -n -r | awk '{ i+=$3; if (i<=200000) {print $2}}' | tar -cvf toto.tar -T -&& ssh -n prd "rm -rf dir/*" && scp toto.tar prd:tmp/ && ssh -n prd "tar xvf tmp/toto.tar"

이 명령은 find로 시작하여 현재 디렉터리(서버 A의 디렉터리 경로에 맞게 조정되어야 함)에서 모든 파일을 찾고 3개 필드를 인쇄합니다.

  • %T@ 유닉스 타임스탬프 인쇄
  • find%p는 시작 시 파일 경로를 인쇄합니다.
  • %s 인쇄 파일 크기(바이트)
  • \n 물론 새로운 줄입니다.

그런 다음 출력이 find정렬되어 sort -n -r첫 번째 필드를 숫자 역순으로 정렬하고 Unix 타임스탬프를 최신 항목에서 가장 오래된 항목 순으로 정렬합니다.

크기 제한을 처리하려면 크기 합계가 제한보다 낮아질 때까지 awk출력의 두 번째 필드를 인쇄하면 약간의 도움이 될 수 있습니다 . sort처리하는 각 행에 대해 세 번째 필드(크기)의 값을 지역 변수로 합산 i한 다음 정렬된 출력의 두 번째 필드를 인쇄합니다( i한도보다 작은 경우).

tar -cvf toto.tar -T -awk출력에서 제공되는 파일 목록에서 toto.tar라는 아카이브가 생성됩니다 .

성공하면 먼저 서버 B의 백업을 삭제한 다음 scp toto.tar host:dir파일을 원격 서버(서버 B)로 전송한 다음 ssh -n "tar xvf dir/toto.tar디렉터리 구조를 유지하면서 전송된 아카이브의 압축을 원격 폴더에 푼다.

이전 scp 기반 솔루션은 디렉터리 구조를 유지하지 않았으므로 이 답변을 편집했습니다.

이것은 최대 크기가 200kb인 내 homedir에서 실행한 결과입니다.

$ rm toto.tar; find . -type f -printf "%T@ %p %s\n"| sort -n -r | awk '{ i+=$3; if (i<=200000) {print $2}}'  | tar -cvf toto.tar -T -&& scp toto.tar prd:tmp/ && ssh -n prd "tar xvf tmp/toto.tar"
./.lesshst
./.viminfo
./scpplus
./.config/xfce4/desktop/icons.screen0-1350x650.rc
./.xsession-errors
./.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-source
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-sink
./.cache/imsettings/log
./.cache/gpg-agent-info
./.ICEauthority
./.vboxclient-draganddrop.pid
./.vboxclient-seamless.pid
./.vboxclient-display.pid
./.vboxclient-clipboard.pid
./.dbus/session-bus/7f14833c645d4a6abb0beba68b79e0c0-0
./.cache/xscreensaver/xscreensaver-getimage.cache
./.config/xfce4/desktop/icons.screen0-1264x950.rc
./work/fpart-0.9.2/src/fpart
toto.tar                                                                                                                              100%  170KB 170.0KB/s   00:00    
./.lesshst
./.viminfo
./scpplus
./.config/xfce4/desktop/icons.screen0-1350x650.rc
./.xsession-errors
./.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-source
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-sink
./.cache/imsettings/log
./.cache/gpg-agent-info
./.ICEauthority
./.vboxclient-draganddrop.pid
./.vboxclient-seamless.pid
./.vboxclient-display.pid
./.vboxclient-clipboard.pid
./.dbus/session-bus/7f14833c645d4a6abb0beba68b79e0c0-0
./.cache/xscreensaver/xscreensaver-getimage.cache
./.config/xfce4/desktop/icons.screen0-1264x950.rc
./work/fpart-0.9.2/src/fpart

가장 큰 문제는 이 솔루션이 메인 서버에서 최신 10gig 데이터를 전송하기 전에 백업 폴더를 삭제한다는 것입니다. 최신 데이터 세트와 백업 데이터 세트에 공통된 파일/디렉토리가 많으면 효율성이 그다지 높지 않습니다. 그러나 이는 최신 데이터의 최신 10gig(또는 무엇이든)를 실제로 추적하는 매우 간단한 방법입니다(빠르고 더러운).

update2: 심심하지만 두 번째 해결책을 설명하겠습니다.

마침내 두 번째 해결책을 찾았습니다. 이제 이에 대해 설명하겠습니다. 코딩하기에는 그다지 효율적이지 않습니다. 쉘 스크립트로 형식화할 수 있고 오류가 발생하거나 이상한 형식의 파일 이름이 있는 경우 기본 검사를 수행하는 대규모 온라인 프로그램입니다.

첫 번째 솔루션의 가장 큰 문제점은 항상 최신 파일 중 마지막 10GB를 백업하려고 한다는 것입니다. 백업된 내용입니다. 즉, 새로 부팅할 때 새 파일이 1억 개만 있는 경우 전체 백업을 지우고 10G 데이터를 다시 전송합니다(최신 100M, 새 9.9G 미만).

이것은 한 줄입니다. ssh -n prd 'cd /var/tmp/test/ && find . -type f -printf "%T@ %p %s\n" ' |awk '{ print int($1)" "$2" "$3 }'|sort -n -r >/tmp/remote ; find . -type f -printf "%T@ %p %s\n" |awk '{ print int($1)" "$2" "$3 }'|sort -n -r | awk '{ i+=$3; if (i<=200000) {print $1" "$2" "$3}}'>/tmp/locale; grep -F -x -v -f /tmp/remote /tmp/locale |cut -d" " -f2 >/tmp/newfile;grep -F -x -v -f /tmp/locale /tmp/remote |cut -d" " -f2 >/tmp/toremove; cat /tmp/toremove |while read i; do echo "removing $i on remote server"; ssh -n prd "rm /var/tmp/test/$i"; done ; cat /tmp/newfile | tar -cvf toto.tar -T -&& scp toto.tar prd:/var/tmp/test/ && ssh -n prd "cd /var/tmp/test; tar xvf /var/tmp/test/toto.tar; rm /var/tmp/test/toto.tar"; rm /tmp/remote /tmp/locale /tmp/toremove /tmp/newfile toto.tar

물론, prd모든 디렉토리 경로(임시 파일 생성 제외)는 로컬/원격 서버뿐만 아니라 서버 B에서도 변경됩니다. 파일 이름 안에 공백이나 특수 문자가 포함된 파일 이름을 처리하지 않도록 주의하세요.

설명하다:

주요 아이디어는 백업되지 않은 백업 서버의 최신 파일이 무엇인지 파악하는 것입니다. 백업 서버에서 너무 오래된 파일을 지우고 크기 제한을 염두에 두고 존재하지 않는 최신 파일만 백업 서버로 전송하세요.

  • 먼저 백업 서버에 연결하여 백업 파일 목록을 가져옵니다. ; 소수 부분을 항상 로 설정하는 ssh -n prd 'cd /var/tmp/test/ && find . -type f -printf "%T@ %p %s\n" ' |awk '{ print int($1)" "$2" "$3 }'|sort -n -r >/tmp/remote ;문제로 인해 가끔 소수 부분을 제거해야 합니다 . 이는 백업 서버와 원본 서버의 날짜가 소수점 이하로 다르다는 것을 의미합니다. 정렬은 첫 번째 필드의 가장 큰 값에서 가장 낮은 값으로 이루어집니다. 즉, 최신 파일에서 가장 오래된 파일 순으로 정렬됩니다. 결과를 파일로 저장합니다. 이전 백업에서는 항상 10G 미만으로 전송했기 때문에 전체 크기를 확인할 필요가 없습니다.tar0/tmp/remote
  • 둘째, 전체 크기가 제한보다 작은 최신 파일 목록을 얻기 위해 로컬에서 동일한 작업을 수행합니다. find . -type f -printf "%T@ %p %s\n" |awk '{ print int($1)" "$2" "$3 }'|sort -n -r | awk '{ i+=$3; if (i<=200000) {print $1" "$2" "$3}}'>/tmp/locale;결과를 다음 위치에 저장합니다./tmp/locale

따라서 실제로 /tmp/locale존재하거나 존재하지 않는 모든 파일은 /tmp/remote동기화할 백업 서버의 최신 파일입니다. 그 안팎의 모든 파일은
삭제할 백업 서버의 파일입니다(너무 오래된 파일)./tmp/remote/tmp/locale

이러한 하위 집합을 구별하기 위해 다음을 사용합니다 grep.

  • grep -F -x -v -f /tmp/remote /tmp/locale |cut -d" " -f2>/tmp/newfile;내가 저장한 포함된 /tmp/locale파일과 포함되지 않은 파일이 모두 표시됩니다./tmp/remote/tmp/newfile
  • grep -F -x -v -f /tmp/locale /tmp/remote |cut -d" " -f2 >/tmp/toremove;/tmp/remote포함된 파일과 포함되지 않은 모든 파일 이 표시됩니다 /tmp/locale./tmp/toremove

이제 디렉터리 구조를 유지하면서 원격으로 삭제할 파일 목록과 백업 서버로 전송할 파일 목록이 생겼습니다.

tar빌드 로캘 아카이브를 사용하여 백업을 보내고, 이전 파일을 원격으로 삭제하고, 아카이브를 전송하고, 압축을 풀겠습니다.

그리고 우리는 거의 끝났습니다. /tmp정리를 위해 임시 파일을 삭제합니다 .

세부 사항은 다음과 같습니다. cat /tmp/toremove |while read i; do echo "removing $i on remote server"; ssh -n prd "rm /var/tmp/test/$i"; done ; 이 루프는 i 파일 목록을 입력으로 읽고, 어떤 파일을 삭제했는지 알려주는 작은 메시지를 표시하고 다음을 통해 cat원격을 시작합니다 .rmssh

cat /tmp/newfile | tar -cvf toto.tar -T -&& scp toto.tar prd:/var/tmp/test/ && ssh -n prd "cd /var/tmp/test; tar xvf /var/tmp/test/toto.tar; rm /var/tmp/test/toto.tar";에 나열된 모든 파일을 포함하는 로케일 toto.tar아카이브가 구축됩니다 /tmp/newfile. 성공하면 원격 서버로 전송하고 원격으로 압축을 풀고 ssh, 다음 부팅에 지장을 주지 않도록 백업 서버의 아카이브도 삭제합니다.

rm /tmp/remote /tmp/locale /tmp/toremove /tmp/newfile toto.tar이 시작 중에 사용된 파일의 로컬 정리입니다.

이 온라인 프로그램은 임시 파일의 사용을 제거하고 출력을 grep루프 whiletar명령으로 직접 파이프하여 단축할 수 있습니다.

scp또한 모든 명령 반환 상태(아카이브를 빌드할 위치가 충분하지 않거나 ssh오류...)와 이상한 파일 이름(매개변수 확장 혼동을 피하기 위해 공백이나 특수 문자 포함)을 처리하도록 개선될 수도 있습니다.

답변2

최근에 비슷한 문제가 발생했습니다. 내가 끝낸 것은 find + rsync였습니다.

#!/usr/bin/env bash
# first prepare the file list I want to sync

find /path -mtime 7 -other-conditions-you-want > /tmp/file.list.$$
rsync --file-from=/tmp/file.list.$$ /source /dest

물론 파일이 원격 서버에 있는 경우 원격으로 찾기를 실행하고 --file-from=:/tmp/file.list.$$를 사용하여 다음과 같이 원격에서 파일 목록을 가져와야 합니다.

ssh "$_SOURCE_HOST" "cd '$_SOURCE_PATH'; find . $MMIN_FLAG -type f > /tmp/$_NAME-$TOKEN"
rsync "--files-from=:/tmp/$_NAME-$TOKEN" "$_SOURCE" "$_DEST"    
ssh "$_SOURCE_HOST" "rm -f /tmp/$_NAME-$TOKEN"

bash에서와 같이 rm명령을 설정하여 trap파일이 마지막에 삭제되도록 할 수 있습니다.

관련 정보