Created
April 20, 2012 19:04
-
-
Save niwinz/2431088 to your computer and use it in GitHub Desktop.
Mini SSH library for python3 based on subprocess
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[[email protected]][~]% python3 subprocess_ssh.py | |
(0, b'Linux vaio.niwi.be 3.3.2-1-ARCH #1 SMP PREEMPT Sat Apr 14 09:48:37 CEST 2012 x86_64 Intel(R) Core(TM)2 Duo CPU T6600 @ 2.20GHz GenuineIntel GNU/Linux') | |
(0, b'processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 23\nmodel name\t: Intel(R) Core(TM)2 Duo CPU T6600 @ 2.20GHz\nstepping\t: 10\nmicrocode\t: 0xa07\ncpu MHz\t\t: 2193.716\ncache size\t: 2048 KB\nphysical id\t: 0\nsiblings\t: 2\ncore id\t\t: 0\ncpu cores\t: 2\napicid\t\t: 0\ninitial apicid\t: 0\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 13\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dts\nbogomips\t: 4389.24\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 36 bits physical, 48 bits virtual\npower management:\n\nprocessor\t: 1\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 23\nmodel name\t: Intel(R) Core(TM)2 Duo CPU T6600 @ 2.20GHz\nstepping\t: 10\nmicrocode\t: 0xa07\ncpu MHz\t\t: 2193.716\ncache size\t: 2048 KB\nphysical id\t: 0\nsiblings\t: 2\ncore id\t\t: 1\ncpu cores\t: 2\napicid\t\t: 1\ninitial apicid\t: 1\nfpu\t\t: yes\nfpu_exception\t: yes\ncpuid level\t: 13\nwp\t\t: yes\nflags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dts\nbogomips\t: 4389.24\nclflush size\t: 64\ncache_alignment\t: 64\naddress sizes\t: 36 bits physical, 48 bits virtual\npower management:\n') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import fcntl | |
import os | |
import select | |
from subprocess import Popen, PIPE | |
def non_block_read(output): | |
fd = output.fileno() | |
fl = fcntl.fcntl(fd, fcntl.F_GETFL) | |
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) | |
try: | |
return output.read() | |
except: | |
return "" | |
class SSHClient(object): | |
shell = "/bin/sh" | |
ssh_path = "/usr/bin/ssh" | |
started = False | |
stoped = False | |
returncode = None | |
def __init__(self, user, host, shell=None, ssh=None): | |
self.user = user | |
self.host = host | |
if shell is not None: | |
self.shell = shell | |
if ssh is not None: | |
self.ssh_path = ssh | |
def _start_ssh_process(self): | |
user_host = "{user}@{host}".format(user=self.user, host=self.host) | |
self.proc = Popen([self.ssh_path, user_host, self.shell], | |
stdin=PIPE, stdout=PIPE, stderr=PIPE) | |
poll_result = self.proc.poll() | |
if poll_result is not None: | |
self.returncode = poll_result | |
return self.read_stderr() | |
self.started = True | |
return None | |
""" | |
Low level methods. | |
""" | |
def _read(self, _file): | |
output = [] | |
while True: | |
_r, _w, _e = select.select([_file],[],[], 0.2) | |
if len(_r) == 0: | |
break | |
data = non_block_read(_r[0]) | |
if data is None: | |
break | |
output.append(data) | |
return b"".join(output) | |
def write(self, data, encoding='utf-8'): | |
if isinstance(data, str): | |
data = bytes(data, encoding) | |
num = self.proc.stdin.write(data) | |
self.proc.stdin.flush() | |
return num | |
def read_stdout(self): | |
return self._read(self.proc.stdout) | |
def read_stderr(self): | |
return self._read(self.proc.stderr) | |
""" | |
High level methods. | |
""" | |
def start(self): | |
if self.started: | |
raise Exception("Already started") | |
self._start_ssh_process() | |
def stop(self): | |
if self.stoped: | |
raise Exception("Already stoped") | |
self.proc.terminate() | |
def execute(self, command, encoding='ascii'): | |
if isinstance(command, str): | |
command = bytes(command, encoding) | |
if command[-1] != b"\n": | |
command = command + b"\n" | |
command += b"echo $?\n" | |
n = self.write(command) | |
result, rcode, *o = self.read_stdout().rsplit(b"\n", 2) | |
return int(rcode), result | |
if __name__ == '__main__': | |
c = SSHClient(user="niwi", host="localhost") | |
c.start() | |
print(c.execute("uname -a")) | |
print(c.execute("cat /proc/cpuinfo")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment