Skip to content

Instantly share code, notes, and snippets.

@alex-bender
Forked from virtuald/sshpass.py
Created July 31, 2017 07:01
Show Gist options
  • Save alex-bender/ac6feb598a5424f9b54c46d24d890a88 to your computer and use it in GitHub Desktop.
Save alex-bender/ac6feb598a5424f9b54c46d24d890a88 to your computer and use it in GitHub Desktop.
Simple python wrapper to give SSH a password for automation purposes (with output capture)
#!/usr/bin/env python3
import os
import sys
_b = sys.version_info[0] < 3 and (lambda x:x) or (lambda x:x.encode('utf-8'))
def ssh_exec_pass(password, args, capture_output=False):
'''
Wrapper around openssh that allows you to send a password to
ssh/sftp/scp et al similar to sshpass.
Not super robust, but works well enough for most purposes. Typical
usage might be::
ssh_exec_pass('p@ssw0rd', ['ssh', '[email protected]', 'echo hi!'])
:param args: A list of args. arg[0] must be the command to run.
:param capture_output: If True, suppresses output to stdout and stores
it in a buffer that is returned
:returns: (retval, output)
*nix only, tested on linux and OSX. Python 2.7 and 3.3+ compatible.
'''
import pty, select
# create pipe for stdout
stdout_fd, w1_fd = os.pipe()
stderr_fd, w2_fd = os.pipe()
pid, pty_fd = pty.fork()
if not pid:
# in child
os.close(stdout_fd)
os.close(stderr_fd)
os.dup2(w1_fd, 1) # replace stdout on child
os.dup2(w2_fd, 2) # replace stderr on child
os.close(w1_fd)
os.close(w2_fd)
os.execvp(args[0], args)
os.close(w1_fd)
os.close(w2_fd)
output = bytearray()
rd_fds = [stdout_fd, stderr_fd, pty_fd]
def _read(fd):
if fd not in rd_ready:
return
try:
data = os.read(fd, 1024)
except (OSError, IOError):
data = None
if not data:
rd_fds.remove(fd) # EOF
return data
# Read data, etc
try:
while rd_fds:
rd_ready, _, _ = select.select(rd_fds, [], [], 0.04)
if rd_ready:
# Deal with prompts from pty
data = _read(pty_fd)
if data is not None:
if b'assword:' in data:
os.write(pty_fd, _b(password + '\n'))
elif b're you sure you want to continue connecting' in data:
os.write(pty_fd, b'yes\n')
# Deal with stdout
data = _read(stdout_fd)
if data is not None:
if capture_output:
output.extend(data)
else:
sys.stdout.write(data.decode('utf-8', 'ignore'))
data = _read(stderr_fd)
if data is not None:
sys.stderr.write(data.decode('utf-8', 'ignore'))
finally:
os.close(pty_fd)
pid, retval = os.waitpid(pid, 0)
return retval, output
if __name__ == '__main__':
retval, _ = ssh_exec_pass(sys.argv[1], sys.argv[2:], False)
exit(retval)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment