32

It turns out rsync can't work with a remote server which has a .bashrc file?

At local client i got when run rsync:

protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(180) [sender=3.0.7]

As suggested here removing the .bashrc on server solved the problem. How to solve it without removing the .bashrc file (temporarily)?

3
  • 2
    Check if ssh is enabled for that account.
    – Yasen
    Commented Jan 4, 2013 at 9:22
  • The below answers are likely incorrect. I recently started getting this error after a routine Ubuntu upgrade, even though nothing changed in my .bashrc files.
    – Cerin
    Commented Feb 19, 2013 at 19:30
  • No - if removing the .bashrc file fixes it (as was stated in this question), then the problem is output from the .bashrc. An upgrade could certainly introduce an actual protocol incompatibility, which is an entirely different issue.
    – Randall
    Commented Aug 1, 2013 at 16:42

8 Answers 8

37

You can run into problems if the .bashrc on the remote server outputs anything to the terminal. Rsync may not expect that and may have problems as a result.

You can fix this by removing any commands in the .bashrc that output text, or by piping any output to /dev/null.

5
  • 5
    So how to pipe any output to /dev/null if i can only modify files on client?
    – Computist
    Commented Aug 23, 2011 at 15:02
  • 1
    I suppose you could as your system administrator for assistance. You may also be able to modify files on the server in another way, such as FTP or scp. Commented Aug 23, 2011 at 19:37
  • 1
    Yeah my .bashrc file contained an echo "*** Starting ROOT Shell ***" and echo "(Please use sudo instead of a root shell whenever possible!)". Removing those echos fixed the problem.
    – Kentgrav
    Commented Apr 12, 2016 at 14:46
  • 2
    From the rsync man page: "protocol version mismatch - is your shell clean?" This message is usually caused by your startup scripts or remote shell facility producing unwanted garbage on the stream that rsync is using for its transport. The way to diagnose this problem is to run your remote shell like this: ssh remotehost /bin/true > out.dat then look at the out.dat file. If everything is working correctly then out.dat should be a zero length file.
    – Kentgrav
    Commented Apr 12, 2016 at 14:51
  • 1
    @Computist you can use something like echo anything >/dev/null 2>&1 . Commented Mar 31, 2022 at 20:28
13

The .bashrc is really not the correct place for generating output, as it causes this kind of problem. A lot of people get away with it, though, until they try to run rsync :-)

Any desired output (and the associated logic and commands) should be moved to your .bash_profile (see, e.g., Server Fault question ".profile vs. .bash_profile vs. .bashrc" for further discussion on the differences between the files).

That way, you won't need to sacrifice getting the output when you login, nor deal with making temporary changes to your .bashrc when you want to use rsync.

12

The problem

For complex reasons rsync/scp/sftp runs .bashrc when connecting to another host. The mere presence of .bashrc is not an issue. Problems arise if any of the commands in .bashrc produces output during a non-interactive session.

A good solution for most cases

Place any of these commands at the top of your .bashrc:

either

# for non-interactive sessions stop execution here -- https://serverfault.com/a/805532/67528
[[ $- != *i* ]] && return

or

# for non-interactive sessions stop execution here -- https://serverfault.com/a/805532/67528
[ -z "$PS1" ] && return

Any of the above commands will only allow the execution of the rest of .bashrc commands for interactive sessions. As far as I know you don't need them for any other type of session (and indeed I have seen default bashrc from Arch and Debian using this technique in their bashrc).

A good solution for rare cases

If you want to be extra paranoid about letting your bashrc commands run even for non interactive sessions you should at least wrap the commands that may produce output like in the example below (reference):

if shopt -q login_shell; then
    # this is an interactive session, we _can_ display output
    ...commands that may produce output goes here...
fi

A solution you should probably avoid

Others suggest moving commands that output text to your bash_profile but I have my doubts about whether this is always good (for reasons explained here)

8

I've always had .bashrc files on my user accounts and never had this problem until I tried today to rsync something to my server using the root account. Your post helped me find the solution:

my $user/.bashrc files always start with the following section to prevent this kind of issue. I replicated it to root's .bashrc and rsync'ing now works like a charm!

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

HTH, karsten

2
  • 1
    This does usually not work for rsync, because it is for whatever reason classified as "interactive shell". But it's a good line to add anyway, because it might screw up non-interactive shells otherwise if there is any output. Commented Aug 18, 2015 at 17:11
  • I think this is the best solution to the question. The accept answer "removing any commands in the .bashrc that output text" is not practical.
    – Qinsi
    Commented Jul 27, 2018 at 5:47
1

All the answers so far assume that there is some problem with the shell, while in fact the issue might be with the protocol version just as the error has stated.

In my case I was trying to rsync files from CentOS 7, which had an old rsync 2.5.6 to Ubuntu 20.04 (which had 3.1.2).

rsync --version
rsync  version 2.5.6  protocol version 26
Copyright (C) 1996-2002 by Andrew Tridgell and others

After I've added --protocol=26 to my rsync invocation on Ubuntu, everything synced fine.

0

I've tried all of the above! compared versions and jagged .basrc The ONLY thing worked for me was a simple 'touch .hushlogin' on ~remote_home_dir.

0

I had the issue with setting colors on ssh following how-to-change-terminal-colors-when-connecting-to-ssh-hosts. My solution was to abandon the coloring.

-1

This burden is because you are running rsync over SSH.

SSH starts your shell scripts, like .bashrc The output of the scripts corrupts RSYNC handshake, a known problem, you get a hint “protocol version mismatch — is your shell clean?”

If you don't need SSH features (like authentication and tunneling), you can run pure rsync without SSH. Just prepend each host with rsync://

rsync over rsync:

  1. You can define its access permissions. See these file

    • /etc/rsyncd.secrets
    • /etc/rsyncd.conf

Note: file locations can be different.

  1. Performance

    Sometimes rsync/rsync is much faster than rsync/ssh. Test with your servers and network.

You must log in to answer this question.

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