I have the following script, which works:
echo -n "Enter sudo password: "
read -s sudo_pass
echo "$sudo_pass" | ssh -tt myhost "sudo -S ./remote_script.sh"
The problem is the output. I'd like the password from stdin
to be used by sudo
, but NOT be printed to the screen. Instead, I get:
<system banner>
thepassw0rd
[sudo] password for theuser:
Is there a way to accomplish this? I'm not even sure which command is causing the input to be printed.
I was able to find that the input is being printed by ssh by just doing:
echo 123 | ssh -tt myhost "sleep 2"
which gave me
<system banner>
123
Connection to myhost closed.
The problem here lies with the -tt
option to ssh
. You are forcing it to allocate a pseudo-terminal. This pseudo-terminal reads stdin and doesn't know whether what it reads comes from your keyboard or a redirection (echo "$sudo_pass" | ssh ...
). So it acts like a terminal and echoes what it receives (because it receives it before sudo
has the time to run and capture stdin).
You are experiencing one of the drawbacks of the -t
option. Another one that hasn't hit you yet is that if your password starts with an ssh
escape sequence (~C
, ~?
, etc) this won't work as expected either.
Easy and best solution: do not use the -tt
option.
If you really cannot do without it - because e.g. your remote script adamantly wants a terminal - one (ugly) solution would be to "eat" the first line that is sent back by ssh
, since you know for sure it will always be your password that is echoed back:
echo "$sudo_pass" | ssh -tt myhost ... | ( read; cat )
Personally, I wouldn't be so sure that the first line would always be the password and I don't recommend this. A far better alternative, is to add a small delay before sending the password, in order to let sudo
start remotely and capture stdin:
( sleep 1; echo "$sudo_pass" ) | ssh -tt myhost ...
But this still is a hack and the best solution is of course to not use ssh
's -tt
option.