Search code examples
bashsshsudo

Bash: How to read password from stdin without echoing over SSH


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.

UPDATE

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.

Solution

  • 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.