기술 · 실용 가이드
Rsync “protocol version mismatch”? shell을 고치기 전에 원격 byte stream을 캡처하세요
불필요한 stdout, SSH forced command, 원격 rsync 부재, 실제 version 경계를 증거로 나누고 --protocol을 맹목적으로 고정하지 마세요.

이 메시지는 client가 받은 첫 byte가 예상한 rsync protocol 대화가 아니라는 뜻이다. startup 출력이 흔하지만 .bashrc를 증명하지는 않는다. ForceCommand, SFTP-only account, PATH, PTY, 오래된 version 경계도 같은 오류를 만든다.
한 transcript에 정확한 command, no-PTY stdout byte, 분리된 stderr, sshd가 허용한 remote command, 양쪽 binary/version, disposable file 검증을 보존한다. 양성 증거가 있는 branch만 변경한다.
실패한 transport 고정
local command, 방향, source/destination, host alias, user, port, 인증 경로, exit code와 두 stream을 기록한다. ssh -G 결과도 보존하되 secret은 공개하지 않는다.
interactive login 성공은 같은 control이 아니다. TTY, startup path, remote command가 다를 수 있다.
PTY 없이 remote stdout byte 캡처
ssh -T remotehost /bin/true >out.bin 2>err.txt를 실행하고 byte 수와 안전한 hex preview를 기록한다. out.bin이 비지 않으면 emitter부터 찾는다.
shell startup, banner, wrapper, shell 초기화를 점검하고 사람용 출력은 interactive session으로 제한한다. -q로 증거를 숨기지 않는다.
stdout이 비면 sshd 실행 command 증명
authorized_keys와 Match block의 command=, ForceCommand, internal-sftp, ChrootDirectory, no-user-rc, wrapper를 확인한다. forced command는 client command를 무시한다.
rsync는 remote rsync --server를 필요로 한다. SFTP-only나 고정 command는 계약 실패다. 필요하면 reviewed allowlist wrapper를 사용한다.
remote binary와 version 명시
같은 noninteractive context에서 command -v rsync와 absolute path --version을 기록해 local과 비교한다. chroot와 PATH가 binary를 감출 수 있다.
stream과 command가 정상일 때만 --protocol을 제한 실험한다. 영구적인 만능 수정이 아니다.
disposable file 하나로 종료
알려진 byte의 작은 file을 no-PTY로 한 번 전송하고 command, version, exit, size, 양쪽 checksum을 기록한다. 실패와 성공 transcript를 같이 둔다.
같은 account/policy에서 예상 command, 추가 byte 없음, file 검증 성공을 확인한 뒤 automation을 복구한다. SFTP-only면 SFTP를 사용한다.
