linuxsshrsyncmanjarox11-forwarding

rsync with X11-Forwarding does not set DISPLAY?


Some context:

What I've done:

I've followed the advice from this post, so the full command I'm running is

rsync -Payz --delete --recursive -e "ssh -X" --rsync-path="sudo -A rsync" user@server:backup .

The issue

Error: Can't open display: 
sudo: no password was provided
sudo: a password is required
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [Receiver=3.2.7]
debug1: X11 forwarding requested but DISPLAY not set
debug1: Sending command: sudo -A rsync --server --sender -logDtprze.iLsfxCIvu . backup
Error: Can't open display: 
sudo: no password was provided
sudo: a password is required
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
debug1: channel 0: free: client-session, nchannels 1
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
Transferred: sent 2176, received 2464 bytes, in 0.2 seconds
Bytes per second: sent 9432.6, received 10681.1
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [Receiver=3.2.7]

so apparently when rsync runs ssh -X here, the DISPLAY variable is left unset


Solution

  • I can only suggest you trace the environment being passed through rsync as follows. Add option -n to do no transfers, and use some /tmp/dummy file. Prefix the command with strace using option -v to see the environment during execve() calls, -f to follow children, and -o log to output to some log file. For example,

    DISPLAY=:0 strace -vf -o /tmp/log rsync -n -Payz  --delete --recursive \
     -e 'ssh -X' --rsync-path='sudo -A rsync' user@server:/tmp/dummy /tmp/dummy
    

    Looking through the log file you should see something like

    5261  execve("/usr/bin/ssh", ["ssh", "-X", "-l", "user", "server", 
     "sudo -A rsync", "--server", "--sender", "-nlogDtprze.iLsfxC", ".",
     "/tmp/dummy"], ["DISPLAY=:0", "SHELL=/usr/bin/bash", ...] <unfinished ...>
    

    (one long line). Beware, you may need to ignore many execve's of ssh that are attempted and fail as each directory in the current PATH is tried. In this example output, 5261 is the process id.

    The execve() system call of /usr/bin/ssh shows the arguments to ssh in the first array [...], and the environment passed to the command in the second array [..."DISPLAY=:0"...]. Ensure "DISPLAY=:0" is in this second array.

    If it isn't, then look earlier in the file for the first execve() of rsync to see if DISPLAY is in the env there. You should find something like:

    5624  execve("/usr/bin/rsync", ["rsync", "-n", "-Payz", "--delete",
     "--recursive", "-e", "ssh -X", "--rsync-path=sudo -A rsync", 
     "user@server:/tmp/dummy", "/tmp/dummy"], [...,"DISPLAY=:0",...]) = 0
    

    You can add a second -f to strace to get separate log files, one for each process, rather than all intermixed.

    If it is in the first execve("/usr/bin/rsync", and not in the later execve("/usr/bin/ssh", that would indeed suggest that rsync has deliberately removed it from the environment. Perhaps this is some sort of new security feature?

    To work round it, create your own shell script "ssh" in your PATH that simply does

    #!/usr/bin/bash
    export DISPLAY=:0; exec /usr/bin/ssh "$@"