로컬 셸을 사용하여 두 원격 호스트 간에 파일을 전송하고 싶지만 다음과 같이 두 원격 호스트를 지정하면 rsync가 동기화를 지원하지 않는 것 같습니다.
$ rsync -vuar host1:/var/www host2:/var/www
The source and destination cannot both be remote.
유사한 결과를 얻기 위해 사용할 수 있는 다른 해결 방법/명령은 무엇입니까?
답변1
아시다시피 원격 소스 및 원격 대상에는 rsync를 사용할 수 없습니다. 두 서버가 서로 직접 통신할 수 없다고 가정하면 SSH를 사용하여 로컬 시스템을 통해 터널을 설정할 수 있습니다.
바꾸다
rsync -vuar host1:/var/www host2:/var/www
당신은 이것을 사용할 수 있습니다
ssh -R localhost:50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /var/www localhost:/var/www'
의 첫 번째 인스턴스는 의 대상에 해당하는 의 /var/www
소스에 적용됩니다 .host1
localhost:/var/www
host2
궁금한 경우 이 -R
옵션은 호스트 1의 포트 50000에서 백채널을 설정합니다. 이 백채널은 (로컬 시스템을 통해) 호스트 2의 포트 22에 매핑됩니다. 호스트 1에서 호스트 2로의 직접 연결은 없습니다.
답변2
한 호스트에 로그인한 다음 다른 호스트에 복사하고 싶지 않은 이유를 말하지 않았으므로 이유와 해결 방법 중 하나를 공유하겠습니다.
두 호스트 모두 다른 컴퓨터에 로그인할 SSH 키가 없기 때문에 한 컴퓨터에 로그인한 다음 다른 컴퓨터에 rsync할 수 없습니다. 로그인할 때 첫 번째 호스트가 내 SSH 키를 사용할 수 있도록 SSH 에이전트 전달을 사용하여 이 문제를 해결했습니다.
경고하다:SSH 전달을 통해 호스트는 로그인 중에 SSH 키를 사용할 수 있습니다. 키를 복사할 수는 없지만 이를 사용하여 다른 컴퓨터에 로그인할 수는 있습니다. 위험을 이해하고 신뢰하지 않는 시스템에 프록시 전달을 사용하지 마십시오.
다음 명령은 SSH 에이전트 전달을 사용하여 에서 으로의 host1
직접 연결을 엽니다 host2
. 이것의 장점은 명령을 실행하는 머신이 전송에 병목 현상을 일으키지 않는다는 것입니다.
ssh -A host1 rsync -vuar /var/www host2:/var/www
답변3
나는 roaima의 답변을 좋아하지만 두 예 모두에서 경로가 동일하여 어느 것이 무엇인지 혼란스럽습니다. 다음 방법이 작동하지 않는 것으로 확인되었습니다.
rsync -vuar host1:/host1/path host2:/host2/path
하지만 그렇습니다( -R
기본값이므로 옵션에서 localhost에 대한 명시적 바인드 주소를 생략했습니다).
ssh -R 50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path'
두 원격 호스트 사이에 SSH 키를 올바르게 설정해야 합니다(host1의 개인 키와 host2의 공개 키).
연결을 디버깅하려면 연결을 두 부분으로 분할하고 자세한 상태를 추가하세요.
localhost$ ssh -v -R 50000:host2:22 host1
이것이 작동하면 호스트 1에 쉘이 있게 됩니다. 이제 Host1에서 rsync 명령을 실행해 보십시오. 자세한 SSH 정보가 rsync 상태 정보와 혼합되지 않도록 다른 창에서 이 작업을 수행하는 것이 좋습니다.
host1$ rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path
답변4
사용하기 쉬운 스크립트
나는 여기의 다른 답변과 거의 동일한 트릭을 사용하여 수년에 걸쳐 이 작업을 여러 번 수행했습니다. 그러나 일부 세부 사항을 잘못 이해하고 문제를 해결하는 데 많은 시간을 소비하기 쉽기 때문에 다음 스크립트를 생각해 냈습니다.
- 모든 세부 정보(소스, 대상, 옵션)를 쉽게 지정할 수 있습니다.
- 각 단계를 단계별로 테스트하고 문제가 발생하면 피드백을 제공하여 무엇을 수정해야 할지 알 수 있습니다.
- 인증 데이터를 전파할 수 없는 상황 수정
ssh -A
(해결 방법이 근본 원인을 찾는 것보다 쉽기 때문에 가끔 이런 일이 발생하는 이유는 확실하지 않음) - 드디어 일을 마쳤습니다.
스크립트 사용 방법
- localhost에서 두 호스트 모두로 SSH를 통해 연결할 수 있는지 확인하세요.아니요암호를 입력.
- 스크립트의 처음 몇 줄에 변수를 설정합니다.
- 실행하세요.
어떻게 작동하나요?
내가 말했듯이 여기의 다른 모든 답변과 동일한 트릭을 사용합니다.
- SSH에 대한 옵션
-R
은 포트 전달을 설정하는 동안 로컬 호스트에서 호스트 1로 ssh를 수행한 다음 호스트 1이 로컬 호스트를 통해 호스트 2에 연결하도록 허용하는 것입니다(-R localhost:$FREE_PORT:$TARGET_ADDR_PORT
). - SSH 옵션을 사용하면
-A
두 번째 SSH 채널을 쉽게 인증할 수 있습니다.
내 건 복잡해! 더 쉬운 방법이 있나요?
소스에서 대상으로 전체 또는 대부분의 바이트를 복사하는 경우멀리사용이 더 쉬워졌습니다 tar
:
ssh $SOURCE_HOST "tar czf - $SOURCE_PATH" \
| ssh $TARGET_HOST "tar xzf - -C $TARGET_PATH/"
스크립트
#!/bin/bash
#-------------------SET EVERYTHING BELOW-------------------
# whatever you type after ssh to connect to SOURCE/TARGE host
# (e.g. 1.2.3.4:22, user@host:22000, ssh_config_alias, etc)
# So if you use "ssh foo" to connect to SOURCE then
# you must set SOURCE_HOST=foo
SOURCE_HOST=host1
TARGET_HOST=host2
# The IP address or hostname and ssh port of TARGET AS SEEN FROM LOCALHOST
# So if ssh -p 5678 [email protected] will connect you to TARGET then
# you must set TARGET_ADDR_PORT=1.2.3.4:5678 and
# you must set TARGET_USER=someuser
TARGET_ADDR_PORT=1.2.3.4:5678
TARGET_USER=someuser
SOURCE_PATH=/mnt/foo # Path to rsync FROM
TARGET_PATH=/mnt/bar # Path to rsync TO
RSYNC_OPTS="-av --bwlimit=14M --progress" # rsync options
FREE_PORT=54321 # just a free TCP port on localhost
#---------------------------------------------------------
echo -n "Test: ssh to $TARGET_HOST: "
ssh $TARGET_HOST echo PASSED| grep PASSED || exit 2
echo -n "Test: ssh to $SOURCE_HOST: "
ssh $SOURCE_HOST echo PASSED| grep PASSED || exit 3
echo -n "Verifying path in $SOURCE_HOST "
ssh $SOURCE_HOST stat $SOURCE_PATH | grep "File:" || exit 5
echo -n "Verifying path in $TARGET_HOST "
ssh $TARGET_HOST stat $TARGET_PATH | grep "File:" || exit 5
echo "configuring ssh from $SOURCE_HOST to $TARGET_HOST via locahost"
ssh $SOURCE_HOST "echo \"Host tmpsshrs; ControlMaster auto; ControlPath /tmp/%u_%r@%h:%p; hostname localhost; port $FREE_PORT; user $TARGET_USER\" | tr ';' '\n' > /tmp/tmpsshrs"
# The ssh options that will setup the tunnel
TUNNEL="-R localhost:$FREE_PORT:$TARGET_ADDR_PORT"
echo
echo -n "Test: ssh to $SOURCE_HOST then to $TARGET_HOST: "
if ! ssh -A $TUNNEL $SOURCE_HOST "ssh -A -F /tmp/tmpsshrs tmpsshrs echo PASSED" | grep PASSED ; then
echo
echo "Direct authentication failed, will use plan #B:"
echo "Please open another terminal, execute the following command"
echo "and leave the session running until rsync finishes"
echo "(if you're asked for password use the one for $TARGET_USER@$TARGET_HOST)"
echo " ssh -t -A $TUNNEL $SOURCE_HOST ssh -F /tmp/tmpsshrs tmpsshrs"
read -p "Press [Enter] when done..."
fi
echo "Starting rsync"
ssh -A $TUNNEL $SOURCE_HOST "rsync -e 'ssh -F /tmp/tmpsshrs' $RSYNC_OPTS $SOURCE_PATH tmpsshrs:$TARGET_PATH"
echo
echo "Cleaning up"
ssh $SOURCE_HOST "rm /tmp/tmpsshrs"