Rsync over SSH getting no tty present

Solution 1:

Sometimes you think too hard about things.

Rsync was not installed on the remote system.

/facepalm

Solution 2:

Putting this here so I can remember & share this trick:

rsync -av -e "ssh -tt" --rsync-path="stty raw -echo; sudo /usr/bin/rsync"   user@${HOSTNAME}:/ ${DEST_DIR}

This method seems to bypass the requirement for a tty as enforced on some system's default /etc/sudoers file with Defaults requiretty. This information was crafted after reviewing this SO question & answers.

In that answer, they recommend removing Defaults requiretty from /etc/sudoers. This is the easier method. However, if you are unable to modify the remote host /etc/sudoers to remove this configuration option, you can try forcing the local rsync to use ssh -tt. This option for ssh is described in the ssh client manual page like this:

Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.

Thus, we force ssh to allocate a pseudo-tty to avoid the error:

Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: standard input: Inappropriate ioctl for device
sudo: sorry, you must have a tty to run sudo

Then, the --rsync-path is overridden with a command to do the following:

stty raw -echo; sudo /usr/bin/rsync

stty raw -echo is to set the line discipline of the remote terminal as pass through. This effectively causes it to behave like a pipe that would be used instead of a pseudo-terminal without -tt.

Then the remote rsync command will be sudo /usr/bin/rsync, which now has a pseudo-tty and will pass the requiretty check for sudo.