88

When following the instructions to do rsync backups given here: http://troy.jdmz.net/rsync/index.html

I get the error "protocol version mismatch -- is your shell clean?"

I read somewhere that I needed to silence the prompt (PS1="") and motd (.hushlogin) displays to deal with this. I have done this, the prompt and login banner (MOTD) not longer appear, but the error still appears when I run:

rsync -avvvz -e "ssh -i /home/thisuser/cron/thishost-rsync-key" remoteuser@remotehost:/remote/dir /this/dir/

Both ssh client and sshd server are using version 2 of the protocol.

What could be the problem?

[EDIT] I have found http://www.eng.cam.ac.uk/help/jpmg/ssh/authorized_keys_howto.html which directs that it is sometimes necessary to "Force v2 by using the -2 flag to ssh or slogin

 ssh -2 -i ~/.ssh/my_private_key remotemachine"

It is not clear this solved the problem as I think I put this change in AFTER the error changed but the fact is the error has evolved to something else. I'll update this when I learn more. And I will certainly try the suggestion to run this in an emacs shell -

5
  • 1
    Do your login scripts output something that's not immediately visible, for example a window title changing command? One way to check this is to run Emacs, type ESC x shell, and do export TERM=xterm; ssh remotehost ls. If any control characters or other spurious output appears, that's what you have to hunt down. May 6, 2011 at 23:13
  • 1
    I was having the same problem. In my case the SSH server was configured to chroot users and to only allow SFTP access so it wasn't possible to run the rsync command from the remote shell. If you have access to the server check for the ForceCommand configuration option in /etc/ssh/sshd_config. If it's set to something that's the problem.
    – devius
    Dec 13, 2012 at 15:05
  • For the record, I've run into a situation where I just gave up with a protocol mismatch. rsync --version output identical on both hosts, interactive and non-interactive ssh completely silent, nothing fancy in authorized_keys... Just doesn't work. I leave this comment for others who are rabbibt holing. Do yourself a favour and try without --rsync-path. You'll probably find your problem has nothing to do with this SO.
    – sheldonh
    Oct 30, 2013 at 9:29
  • @sheldonh: did the path on local and remote machine differ in your case? in my case they're the same anyway and giving or not giving it (--rsync-path) doesn't change a thing for me. Jul 28, 2016 at 14:49
  • 1
    @0xC0000022L Sorry, I can't remember.
    – sheldonh
    Aug 11, 2016 at 10:49

12 Answers 12

91

One of your login scripts (.bashrc/.cshrc/etc.) is probably outputting data to the terminal (when it shouldn't be). This is causing ssh to error when it is connecting and getting ready to copy as it starts receiving extra data it doesn't expect. Remove output that is generated in the startup scripts.

You can check if your terminal is interactive and only output text by using the following code in a bashrc. Something equivalent exists for other shells as well:

if shopt -q login_shell; then
    [any code that outputs text here]
fi

or alternatively, like this, since the special parameter - contains i when the shell is interactive:

if echo "$-" | grep i > /dev/null; then
    [any code that outputs text here]
fi

For more information see: rsync via ssh from linux to windows sbs 2003 protocol mismatch

To diagnose this, make sure that the following is the output you get when you ssh in to the host:

USER@HOSTNAME's password: 
Last login: Mon Nov  7 22:54:30 2011 from YOURIP
[USER@HOSTNAME ~]$ 

If you get any newlines or other data you know that extra output is being sent. You could rename your .bashrc/.cshrc/.profile/etc. files to something else so that they won't output extra output. Of course there is still system files that could cause this. In that case, check with your sysadmin that the system files don't output data.

3
  • 6
    An echo in the ~/.bashrc, Thx. You made my day Jan 28, 2016 at 21:18
  • you saved my day!!!!! ...but not the last night..:/..
    – Nikita
    Aug 16, 2021 at 11:05
  • looks like there's no easy way to do this if running rsync over ssh. Jan 26, 2022 at 1:31
29

Troubleshooting this problem:

There is a simple way to test if your shell is clean, for an ssh connection: run a command from the ssh connection, rather than starting an interactive shell. The false command will immediately terminate without producing any output, so it is a good test:

bash$ ssh remotehost false
Enter passphrase for key '/home/user/.ssh/my_private_key': 
bash$

If that command line produces any output, one of your startup scripts is to blame:

bash$ ssh remotehost false
Enter passphrase for key '/home/user/.ssh/my_private_key': 
Welcome to RemoteHost!

This system is company property and is provided for authorized use only, 
as set forth in applicable written policies. Unauthorized use is prohibited 
and may be subject to discipline, civil suit and criminal prosecution.
 
Welcome back - You last logged in 16 days ago...
bash$

Another thing to check if you are getting this error is whether rsync is installed and locatable by ssh:

bash$ ssh remotehost "rsync --version"
Enter passphrase for key '/home/user/.ssh/my_private_key': 
rsync  version 3.0.9  protocol version 30
Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.
Web site: http://rsync.samba.org/
Capabilities:
    64-bit files, 64-bit inums, 64-bit timestamps, 64-bit long ints,
    socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace,
    append, ACLs, xattrs, iconv, symtimes

rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you
are welcome to redistribute it under certain conditions.  See the GNU
General Public Licence for details.
bash$

If rsync is not in the path, you will instead see something like:

bash$ ssh remotehost "rsync --version"
Enter passphrase for key '/home/user/.ssh/my_private_key': 
bash: rsync: command not found
bash$

You can fix this by either installing rsync, or if it is installed but in an unusual location, passing the location to the rsync command line:

rsync -avvvz -e "ssh -i /home/thisuser/cron/thishost-rsync-key" \
    --rsync-path="/usr/local/bin/rsync" \
    remoteuser@remotehost:/remote/dir /this/dir/
2
  • 1
    Another common reason this can fail is if the remote user shell is set to nologin, which outputs a message saying This account is currently not available. which likewise breaks the rsync protocol. May 17, 2021 at 9:08
  • Good pickup @JosipRodin. The tests above will catch this scenario, but the resolution is slightly different.
    – Stobor
    May 24, 2021 at 5:04
12

This is commonly caused by your shell's login stuff outputting stuff on a non-interactive shell. You can test if this is the case by doing:

ssh username@host "/bin/true" > testfile
ls -l testfile

If testfile is NOT 0 bytes, then the trouble is that your shell is outputting something. Check /etc/profile, .profile, .bashrc, .cshrc, etc. If it is, you can change it to check if your terminal is interactive and only output text by using the following code in a bashrc. Something equivalent exists for other shells as well:

if shopt -q login_shell; then
    [any code that outputs text here]
fi

or alternatively, like this, since the special parameter - contains i when the shell is interactive:

if echo "$-" | grep i > /dev/null; then
    [any code that outputs text here]
fi

However, if the test file is in fact 0 bytes, then your shell is behaving, but it is possible that you just have a very old version of rsync. You can tell the client end (assuming it is the newer end) to not advertise such a high version that the old rysnc server version doesn't recognize it. You can do this using the --protocol= option. In my case, using --protocol=30 did the trick.

If you are still having trouble, try ssh in as the user rsysnc is connecting with and try running rsync --version to see if the shell can find rsync. If you get something that says command not found, then rsync might not be installed on the machine you are connecting to or it might not be in the path. Rsync does have options for specifying the path of the remote end, read the man page(s).

2
  • 1
    +1 for the hint about --protocol which solved my problem with a 2.5.6 server (protocol version 26) and a 3.1.0 client (protocol version 31)
    – MattBianco
    Feb 16, 2016 at 7:45
  • 1
    Sometimes the output can be subtle. I had set shopt -s cdable_vars on the remote, then had a cd to a variable without $. With this option set, it will change to the correct directory, but output the actual cd command to the shell, which is what triggered this message. Wrapping the cd in the shopt -q login_shell test fixed it.
    – Liam
    Jan 11, 2022 at 17:17
5

This is a special case from the other replies, but is not very different from then.

To execute a rsync via ssh, you need shell access in ssh to execute the remote rsync command. If your ssh account only allows scp/sftp, you will not be able to start the remove rsync and fails giving this error.

This can be tested with the same command as above

ssh remotehost false

This one should fail and this one should be success

sftp remotehost

This proves that you have a sftp only access.

If you want and have permissions to do so, you can disable the sftp only access for that user, by editing the /etc/ssh/sshd_config and check for match and forcecommand entries.

You can also check this post

5

I got protocol version mismatch -- is your shell clean? simply because I hadn't installed rsync on the other end yet. sudo yum install rsync solved the problem.

2
  • Spent 30 minutes messing with a container and Ansible wondering why rsync wasn't working... hard for it to work when it's not installed! Thanks ;)
    – Ryan
    Mar 12, 2018 at 7:21
  • Too bad it doesn't provide a more sensible error message in this case. Aug 26, 2023 at 14:28
4

I also observe this error when pulling files from an instance with rsync version 2.5.7 protocol version 26 to version 3.1.1:

protocol version mismatch - is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(62)
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [Receiver=3.1.1]

But the remote shell had no login banner. Instead, the solution was to specify an older protocol (ref):

rsync --protocol=29 ...
2

The prompt will not be shown at all when directly executing a command, and non-interactively so. A simple google turns up first result: http://marc.info/?l=rsync&m=100263876212594&w=2 And since the shell can potentially be invoked, it must not display anything in non-interactive mode — like, when typing just "bash" into an existing prompt, nothing but the new prompt should appear.

3
  • Perhaps I did not make it sufficiently clear but I have already done this "prompt (PS1="") and motd (.hushlogin)". The login indeed does not show any prompt. Despite this the protocol mismatch error still appears. Thanks though - much appreciate the suggestion.
    – rfreytag
    May 6, 2011 at 22:09
  • You basically mentioned this already, but I've had problems like this if there is anything in the .bashrc (or other profile script) that echos anything to the screen. I've even had this kind of problem when running certain programs in the shell that changes things in a certain way (for example, I wasn't able to change my shell with chsh, so I had my .cshrc run bash to change my shell, and ssh wouldn't work anymore).
    – lsd
    May 6, 2011 at 23:02
  • Well that is certainly interesting. I wonder how I might diagnose this since executing the rsync command interactively shows nothing echoed to the screen and the login is completely silent? Hmmm...I wonder if there is something amiss with the shell as you suggest. Thanks.
    – rfreytag
    May 7, 2011 at 1:30
1

This can be caused by an login message on the remote host such as "Your password is going to expire in 6 days" which RSYNC does not expect

1

I found another case, if the default shell of your server is zsh, then you need to check other files like .zshenv, .zprofile, .zshrc etc. Avoid them having "echo"

Use @Stabledog 's method for debug.

1
0

In my case, the solution was as easy as removing the line cat /etc/motd line in ~/.bashrc.

0

Thank you Azendale, upon running your test I found that the file was not 0 bytes. So I went into all of my startup scripts specifically .bashrc and commented out...

#echo -e "Welcome to $LLVER ${USER}"
#echo " "
#date "+%A %d %B %Y, %T"
#free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'
#df -h | awk '$NF=="/"{printf "Disk Usage: %d/%dGB (%s)\n", $3,$2,$5}'
#echo "Support - https://www.linuxliteos.com/forums/ (Right click, Open Link)"
#echo "

I also deleted (well I copied them for backup) all the files in /etc/update-motd before I did this but I cannot definitely say if this had an impact on the solution. All I know is that scp finally works like it is supposed to and I'm happy.

2
  • Welcome to ServerFault. Did you mean that you commented this out?
    – chicks
    Dec 2, 2021 at 3:41
  • Yes, I commented out the the list above, sorry I said uncommented. Dec 3, 2021 at 21:12
0

Just to add to a set of answers, in my case the issue was being caused by SSH rc file that's been set up on the target host.

$ rsync -avz -e "ssh -i ~/.ssh/id_rsa" --progress testfile user@target-host:/home/user/
TERM environment variable not set.
protocol version mismatch -- is your shell clean?
(see the rsync manpage for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(608) [sender=3.2.4]

Moving ~/.ssh/rc file on the target host to a location outside of ~/.ssh allowed rsync to work.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .