Rsync over SSH getting no tty present
I'm using the following command in root's crontab on Debian.
rsync -vqrlHEAXogDtzhi --log-file=${LOG} --progress --rsync-path="sudo /usr/bin/rsync" --exclude-from=$CONFIG_DIR/excludes -e "ssh -i /home/backups/.ssh/id_rsa" backups@${HOSTNAME}:/ ${BACKUP_DIR}
And I'm getting the following:
sudo: no tty present and no askpass program specified
I have tried adding -t to the ssh command and I get:
Pseudo-terminal will not be allocated because stdin is not a terminal.
I have tried adding -t -t to the ssh command and I get:
protocol version mismatch -- is your shell clean?
I have added a .hushlogin to the backups user on the remote box and confirmed that I can ssh as backups using a key to the remote box with nothing displayed (login is hushed). I still get these messages.
Note that I can ssh as backups to the remote box using a key successfully.
Note that my sudo does not have the -tt option.
Note that the following is set in source and destination's /etc/sudoers file:
backups ALL= NOPASSWD:/usr/bin/rsync
Note that my /etc/sudoers file does not have any reference to:
Defaults requiretty
Note that I won't echo my password in the command.
How can I skin this cat? :|
Thanks
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
.
Solution 3:
- You don't need
sudo
if thecron
job is excecuting as root. - There's a whole slew of unnecessary flags:
-rlptgoD
; remove and replace with-a
. - The TTY message from
sudo
is for the local TTY whereas the-t
option tossh
is for the remote TTY. Don't confuse the two. - Don't
-v
and-q
contradict each other? - Your last worry should be whether the local SSH private key is encrypted or not. The former cannot be used with unattended runs (e.g., ones where
stdin
is not a TTY; they aren't run from a terminal or terminal emulator).
EDIT/UPDATE:
- I take back 1 and 2.
- 3 should be about there being no local TTY when
cron
is running, and SSH doesn't allocate one remotely since there isn't a local one.