1

I have gone through multiple threads which has similar questions (Use subprocess to send a password) and have tried number of things but still i am not able to get it to work. Basically i want to push my ssh-keys to a bunch of machines and i am trying to do that with subprocess. But somehow subprocess.Popen fails to get the password and hence it gets stuck.

Below are some of things I have tried.

from subprocess import Popen, PIPE

p = Popen(['ssh-copy-id', 'testbox1'], stdin=PIPE, stdout=PIPE).communicate(input=b'mypassword')

I have also tried supplying the password by writing to process's stdin channel like below

p.stdin.write(b'mypassword')
p.stdin.flush()

I have tried this in both python 2.7 and python and it didn't work. I have also tried providing a linefeed as well after the password but even that didn't work. I am not sure what i am missing here.

I know people have suggested to use Pexpect for this but then again i am more keen in knowing why subprocess can't handle this.

I know there are multiple libraries like Paramiko and also fabric which handles remote connections with much ease, but i don't think that can be used in this case as i am not directly sshing to a machine and rather using ssh-copy-id command from my local machine

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Rohit
  • 3,659
  • 3
  • 35
  • 57
  • I would do some debugging first. See https://unix.stackexchange.com/questions/36540/why-am-i-still-getting-a-password-prompt-with-ssh-with-public-key-authentication/ for a decent starting place. – Chris Beard Nov 28 '18 at 14:08
  • 1
    you could try `p.stdin.write(b'mypassword\n')` (with a linefeed). But those silent entry methods are sometimes more low-level, and it doesn't work. Check if the command doesn't take a password as parameter (`plink` from Putty does) – Jean-François Fabre Nov 28 '18 at 14:09
  • @Jean-FrançoisFabre i tried with linefeed as well and it didn't work. – Rohit Nov 28 '18 at 14:16
  • @Rohit Give this a try? https://serverfault.com/a/306675 – Chris Beard Nov 28 '18 at 14:17
  • 1
    `ssh-copy-id` isn't reading from standard input; it's trying to read directly from the terminal. – chepner Nov 28 '18 at 14:22
  • @ChrisBeard I don't think you are understanding the question. This is a question about python `subprocess.Popen` and not about ssh. I know how to setup passwordless auhtentication on the shell but i want to automate this process with python as i have multiple machines. – Rohit Nov 28 '18 at 14:23
  • @Rohit it is on the contrary _very_ specific to `ssh`. Commands which read the typed keys from lowlevel won't react to stdin redirection. – Jean-François Fabre Nov 28 '18 at 14:24
  • @Jean-FrançoisFabre so there is no way to do this from python ? – Rohit Nov 28 '18 at 14:26
  • it's possible but depends on the terminal. I know how to do from windows for instance. – Jean-François Fabre Nov 28 '18 at 14:36
  • @Jean-FrançoisFabre can you tell how you do on windows ? I mean what's the way to read from terminal with Popen ? – Rohit Nov 28 '18 at 14:52
  • sending key events maybe: https://stackoverflow.com/questions/13564851/how-to-generate-keyboard-events-in-python – Jean-François Fabre Nov 28 '18 at 14:54
  • @Rohit If you look at sshpass, like the serfault link shows, you won't need to enter a password... – Chris Beard Nov 28 '18 at 16:58
  • @ChrisBeard I know about sshpass but that is not what i want to do. Also sshpass does not come shipped with the OS you have to install it to use it. Finally ssh pass is a solution to pass the password to ssh related through shell, my question was very specific to a python module. – Rohit Nov 29 '18 at 08:41

1 Answers1

1

It seemed it was way to tricky to be handled with subprocess and hence i had to pexpect to solve this and it worked in first go.

import pexpect
from getpass import getpass

pwd = getpass("password: ")

child = pexpect.spawn('ssh-copy-id testbox1')
child.expect('.*ssword.*:')
child.sendline(pwd)
child.expect(pexpect.EOF, timeout=None)
cmd_show_data = child.before
cmd_output = cmd_show_data.split('\r\n')
for data in cmd_output:
    print data
Rohit
  • 3,659
  • 3
  • 35
  • 57