So I'm aware that you can use Pexpect
to solve the issue but i'd like to not rely on additional libraries to solve the issue other than those supplied with Python3.
I'm also aware the generating public keys and allowing them on the remote host is ideal, but that's sort of what i intend to use this script for (setting up keys in the right place etc).
This is as far as I've gotten on "my own" with a bunch of help from the SO community.
I'm sort stuck checking if the forked child pseudo terminal is done executing what it's supposed to or not. Meaning i can tell if the SSH is done executing or not because it will live on for as long as the run()
function is operating.
(my pid_exists
will return True
for as long as it's within the run() operation. And if i exit run()
to quickly the SSH session will not have enough time to do what it's supposed to do)
#!/usr/bin/python
import pty, sys
from subprocess import Popen, PIPE, STDOUT
from time import sleep
from os.path import expanduser, abspath
from os import walk, setsid, fork, waitpid, execv, read, write, kill
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
if pid < 0:
return False
try:
kill(pid, 0)
except (OSError, e):
return e.errno == errno.EPERMRM
else:
return True
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt', user='root', password=b'SuperPassword'):
self.exec = execute
self.host = host
self.user = user
self.password = password
self.run()
def run(self):
command = [
'/usr/bin/ssh',
self.user+'@'+self.host,
'-o', 'NumberOfPasswordPrompts=1',
self.exec,
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
while True:
output = read(child_fd, 1024).strip()
print(output)
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif 'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
elif 'company privacy warning' in lower:
pass # This is an understood message
else:
print('Error:',output)
sleep(5)
print(pid_exists(pid))
ssh('10.10.10.1')
I can't find much (or any) information on how to get the execution process of the pseudo-pseudo terminal which Python opens and pipes to me. Can I or should I involve subprocess as explained here: https://stackoverflow.com/a/12235442/929999 or is there another way?
sigh.. One more google could have spared everyone the trouble.
how to give subprocess a password and get stdout at the same time