4

My question can be seen as an extension of How do diff over ssh? with a little twist.

Environment

macOS Sierra (10.12.3)
OpenSSH 7.3

Example situation

I am trying to print a diff between two files, one of them is located on a remote host and requires sudo for reading.

If this remote file was readable by my remote user (or if I could execute the command with the sudo flag NOPASSWD) I would simply execute:

diff LOCALFILE <(ssh host 'cat REMOTEFILE')

However I do need to authenticate in order to execute the remote command, which means I have to allocate a pseudo-terminal with ssh -t, and the following execution never completes:

diff LOCALFILE <(ssh -t host 'sudo cat REMOTEFILE')

Troubleshooting

ps shows me that the ssh process is stopped:

STAT     TIME   COMMAND
S+    0:00.00   diff LOCALFILE /dev/fd/12
T     0:00.03   ssh -t host sudo cat REMOTEFILE

The ssh process does not respond to SIGTERM at that point, and the file descriptor above does not exist:

❯ ls -l /dev/fd
total 0
crw--w----  1 me     tty     16,   2 Feb 23 17:36 0
crw--w----  1 me     tty     16,   2 Feb 23 17:36 1
crw--w----  1 me     tty     16,   2 Feb 23 17:36 2
dr--r--r--  1 root   wheel         0 Feb 23 09:33 4

Extra notes

I can observe the exact same behavior any time I use ssh -t within a process substitution, regardless of whether a password is needed or not for sudo (that said I understand the use of -t is questionable if no input is expected on the remote host).

Bottom line

I'm using diff as an example here, but my question is actually more general: is there any way to use a Bash process substitution together with a SSH pseudo-terminal allocation?

  • http://serverfault.com/q/111064/126632 – Michael Hampton Feb 23 '17 at 17:03
  • I don't have `requiretty` set, besides my problem is that I actually want to use a tty in that case. – Antoine Cotten Feb 23 '17 at 17:27
  • Why do you think you want a tty? What would it possibly gain you? – Michael Hampton Feb 23 '17 at 17:29
  • I need to pass my password as input when I execute `sudo` as explained in my question, changing that behavior is not an option. – Antoine Cotten Feb 23 '17 at 17:33
  • Oh, so that's why it doesn't work. – Michael Hampton Feb 23 '17 at 17:35
  • That was the whole point of the question :) (cf. title and last line). I do appreciate the response though. – Antoine Cotten Feb 23 '17 at 17:40
  • 1
    `That was the whole point of the question` - It is often best to make your question **title** the most specific version of your question. Something like "Provide sudo password over ssh while using process substitution" instead of the more generic option you used. Having a specific title and first sentence really is really the best way to get good answers and comments. – Zoredache Feb 23 '17 at 17:44
  • 1
    This honestly sounds like a job for `expect`, if it is/can be installed on the server. You *might* be able to get it to work with expect installed locally. If you just run `ssh -t host sudo cat REMOTEFILE` alone, do you see the sudo password prompt? – DerfK Feb 23 '17 at 18:25
  • I don't see any prompt, and I can observe the same behavior regardless of whether the sudo command requires a password input or not (i.e. stopped ssh process, no fs, diff seems to hang). As Michael said it's questionable to request a tty if no input is needed, but I was curious to try. – Antoine Cotten Feb 23 '17 at 19:52

1 Answers1

2

You can force sudo to take the password from STDIN using the -S option, per this superuser post. Thus the syntax diff LOCALFILE <(ssh host 'echo <password> | sudo -S cat REMOTEFILE') should do what you need, without the need for a pseudo-terminal.

Jeremy Dover
  • 318
  • 1
  • 6
  • 1
    That works indeed, thanks! I decided to export my password in the environment and use `diff LOCALFILE <(echo $SUDOPASS | ssh host 'sudo -S cat REMOTEFILE')`. – Antoine Cotten Feb 24 '17 at 11:40