class MySshClient(): def __init__(self): self.config = configparser.ConfigParser() self.filename = os.path.join(os.path.dirname(__file__), args.filename).replace("\\", "/") self.config.read(self.filename) self.ssh_client = SSHClient() self.shell = None # 此函数用于输入用户名密码登录主机 def ssh_login(self): try: # 设置允许连接known_hosts文件中的主机(默认连接不在known_hosts文件中的主机会拒绝连接抛出SSHException) self.ssh_client.set_missing_host_key_policy(AutoAddPolicy()) self.ssh_client.connect(hostname=self.config.get('ssh', 'host'), port=self.config.get('ssh', 'port'), username=self.config.get('ssh', 'username'), password=self.config.get('ssh', 'password')) except AuthenticationException: logging.warning('username or password error') return False except NoValidConnectionsError: logging.warning('connect time out') return False except: logging.warning('unknow error') print("Unexpected error:", sys.exc_info()[0]) return False return True # 此函数用于执行command参数中的命令并打印命令执行结果 def execute_some_command(self,command): try: stdin, stdout, stderr = self.ssh_client.exec_command(command) readlines = stdout.readlines() str1 = stdout.read().decode() for line in readlines: print(line) except Exception as e: logging.error(str(e)) def multi_run_comment(self, command_list): if not self.shell: self.shell = self.ssh_client.invoke_shell() try: for cmd in command_list: print("do cmd", cmd) self.shell.send(cmd + '\n') time.sleep(0.8) recved_buff = self.shell.recv(1024) print('recved_buff', recved_buff) except Exception as e: logging.error(str(e)) # 此函数用于退出登录 def ssh_logout(self): logging.warning('will exit host') self.ssh_client.close()
import time from paramiko.client import SSHClient, AutoAddPolicy, socket hosts_filename = os.path.expanduser("~/.ssh/paramiko_known_hosts") #print hosts_filename client = SSHClient() if os.path.isfile(hosts_filename): client.load_host_keys(hosts_filename) #'~/.ssh/known_hosts' client.set_missing_host_key_policy(AutoAddPolicy()) print client.get_host_keys() client.connect('localhost', 2200, username='******', password='******') client.save_host_keys(hosts_filename) #print client.get_host_keys() channel = client.invoke_shell() channel.settimeout(0) #time.sleep(1) def datas(data=''): while True: try: res = channel.recv(10000) if len(res) == 0: exit(0) data += res cmds = data.split('\n') for r in cmds[:-1]: yield r data = cmds[-1] except socket.timeout: pass
class sshWidget(QtWidgets.QWidget): signalShowText = QtCore.Signal() def __init__(self, addr, usr, pwd, pk = None, kf = None): super().__init__() self.initialize(addr, usr, pwd, pk, kf) def initialize(self, addr, usr, pwd, pk, kf): try: self.signalShowText.connect(self.ShowText) self.hasEndedScreen = False self.interactiveWidget = QtWidgets.QTextEdit(self) self.interactiveWidget.setFont(QtGui.QFont({ 'win32': 'Consolas', 'linux': 'Monospace', 'darwin': 'Andale Mono' }.get(sys.platform, 'Courier'), 10)) #self.interactiveWidget.setFocusPolicy(QtCore.Qt.ClickFocus) self.interactiveWidget.setStyleSheet("background-color : green; color : #cccccc;") self.interactiveWidget.installEventFilter(self) self.interactiveWidget.selectionChanged.connect(self.interactiveWidget.copy) self.interactiveWidget.setContextMenuPolicy(QtCore.Qt.NoContextMenu) self.interactiveWidget.setCursorWidth(5) lay = QtWidgets.QHBoxLayout() lay.addWidget(self.interactiveWidget) self.setLayout(lay) # proc vt stream self.defaultLines = 240 self._vt = pyte.Screen(self.defaultLines, 120) self.stream = pyte.Stream() self.stream.attach(self._vt) # connect to ssh (host, port) = addr.split(':') self.ssh = SSHClient() self.ssh.set_missing_host_key_policy(AutoAddPolicy()) self.ssh.connect(host, port=int(port), username=usr, password=pwd, pkey = pk, key_filename=kf) self.shell = self.ssh.invoke_shell() self.thread = threading.Thread(target = ThreadRun, args = (self, ), daemon = True) self.thread.start() return True except Exception as e: traceback.print_exc() return False def run(self): time.sleep(0.5) while True: try: buf = self.shell.recv(999) if len(buf) < 1: break self.stream.feed(buf.decode("utf-8")) self.signalShowText.emit() except Exception as e: self.stream.feed("the network is wrong for: %s"%(traceback.format_exc())) self.signalShowText.emit() break @QtCore.Slot() def ShowText(self): try: self.interactiveWidget.setPlainText("\n".join(self._vt.display)) self.hasEndedScree = self.hasEndedScreen or (self._vt.cursor.y + 1) >= self._vt.lines tc = self.interactiveWidget.textCursor() tc.setPosition(self._vt.cursor.y * (self._vt.columns + 1) + self._vt.cursor.x, QtGui.QTextCursor.MoveAnchor) self.interactiveWidget.setTextCursor(tc) self.interactiveWidget.setFocus() except Exception as e: traceback.print_exc() def mousePressEvent(self, QMouseEvent): if QMouseEvent.button() == QtCore.Qt.RightButton: clipText = QtWidgets.QApplication.clipboard().text() if clipText: # send the clip text to ssh server when right click self.Send(clipText) else: pass def resizeEvent(self, event): if hasattr(self, "_vt"): sz = QtGui.QFontMetrics(self.font()).size(0, " ") columns = int(event.size().width() / sz.width()) self._vt.resize(self.defaultLines, columns) self.ShowText() super().resizeEvent(event) def eventFilter(self, obj, event): if obj == self.interactiveWidget: if event.type() == QtCore.QEvent.KeyPress: self.Send( { QtCore.Qt.Key_Tab: "\t", QtCore.Qt.Key_Backspace: "\x7f", QtCore.Qt.Key_Up: "\033[A", QtCore.Qt.Key_Down: "\033[B", QtCore.Qt.Key_Left: "\033[D", QtCore.Qt.Key_Right:"\033[C" }.get(event.key(), event.text())) return True return False def Send(self, text): try: self.shell.send(text) except Exception as e: traceback.print_exc() def destroy(self, v1, v2): try: self.shell.close() self.ssh.close() self.thread.join() except Exception as e: traceback.print_exc() return super().destroy(v1, v2)
licenses_status = dict() # Connecting to devices and retrieving licenses status for host in credentials.keys(): print('Host:', host) print('Firmware Version:', credentials[host]['version']) try: client.connect( credentials[host]['ip'], port=credentials[host]['port'], username='******', password=credentials[host]['pwd'] ) channel = client.invoke_shell() wait_prompt(30) if credentials[host]['version'] == '5': channel.send('show status\n') licenses_status[host] = search_licenses_v5(30) elif credentials[host]['version'] == '6': channel.send('show license status\n') licenses_status[host] = search_licenses_v6(30) for key, license in licenses.get(credentials[host]['version'], {}).items(): print(license, '|', licenses_status.get(host).get(key)) print('==============================') channel.send('exit\n') channel.close()
class SSH: def __init__(self, hostname, port=22, username='******', pkey=None, password=None, default_env=None, connect_timeout=10): self.stdout = None self.client = None self.channel = None self.sftp = None self.eof = 'Spug EOF 2108111926' self.already_init = False self.default_env = self._make_env_command(default_env) self.regex = re.compile(r'Spug EOF 2108111926 (-?\d+)[\r\n]?') self.arguments = { 'hostname': hostname, 'port': port, 'username': username, 'password': password, 'pkey': RSAKey.from_private_key(StringIO(pkey)) if isinstance(pkey, str) else pkey, 'timeout': connect_timeout, 'banner_timeout': 30 } @staticmethod def generate_key(): key_obj = StringIO() key = RSAKey.generate(2048) key.write_private_key(key_obj) return key_obj.getvalue(), 'ssh-rsa ' + key.get_base64() def get_client(self): if self.client is not None: return self.client self.client = SSHClient() self.client.set_missing_host_key_policy(AutoAddPolicy) self.client.connect(**self.arguments) return self.client def ping(self): return True def add_public_key(self, public_key): command = f'mkdir -p -m 700 ~/.ssh && \ echo {public_key!r} >> ~/.ssh/authorized_keys && \ chmod 600 ~/.ssh/authorized_keys' exit_code, out = self.exec_command_raw(command) if exit_code != 0: raise Exception(f'add public key error: {out}') def exec_command_raw(self, command, environment=None): channel = self.client.get_transport().open_session() if environment: channel.update_environment(environment) channel.set_combine_stderr(True) channel.exec_command(command) code, output = channel.recv_exit_status(), channel.recv(-1) return code, self._decode(output) def exec_command(self, command, environment=None): channel = self._get_channel() command = self._handle_command(command, environment) channel.send(command) out, exit_code = '', -1 for line in self.stdout: match = self.regex.search(line) if match: exit_code = int(match.group(1)) line = line[:match.start()] out += line break out += line return exit_code, out def _win_exec_command_with_stream(self, command, environment=None): channel = self.client.get_transport().open_session() if environment: channel.update_environment(environment) channel.set_combine_stderr(True) channel.get_pty(width=102) channel.exec_command(command) stdout = channel.makefile("rb", -1) out = stdout.readline() while out: yield channel.exit_status, self._decode(out) out = stdout.readline() yield channel.recv_exit_status(), self._decode(out) def exec_command_with_stream(self, command, environment=None): channel = self._get_channel() command = self._handle_command(command, environment) channel.send(command) exit_code, line = -1, '' while True: line = self._decode(channel.recv(8196)) if not line: break match = self.regex.search(line) if match: exit_code = int(match.group(1)) line = line[:match.start()] break yield exit_code, line yield exit_code, line def put_file(self, local_path, remote_path): sftp = self._get_sftp() sftp.put(local_path, remote_path) def put_file_by_fl(self, fl, remote_path, callback=None): sftp = self._get_sftp() sftp.putfo(fl, remote_path, callback=callback) def list_dir_attr(self, path): sftp = self._get_sftp() return sftp.listdir_attr(path) def sftp_stat(self, path): sftp = self._get_sftp() return sftp.stat(path) def remove_file(self, path): sftp = self._get_sftp() sftp.remove(path) def _get_channel(self): if self.channel: return self.channel counter = 0 self.channel = self.client.invoke_shell() command = 'set +o zle\nset -o no_nomatch\nexport PS1= && stty -echo\n' if self.default_env: command += f'{self.default_env}\n' command += f'echo {self.eof} $?\n' self.channel.send(command.encode()) while True: if self.channel.recv_ready(): line = self._decode(self.channel.recv(8196)) if self.regex.search(line): self.stdout = self.channel.makefile('r') break elif counter >= 100: self.client.close() raise Exception('Wait spug response timeout') else: counter += 1 time.sleep(0.1) return self.channel def _get_sftp(self): if self.sftp: return self.sftp self.sftp = self.client.open_sftp() return self.sftp def _make_env_command(self, environment): if not environment: return None str_envs = [] for k, v in environment.items(): k = k.replace('-', '_') if isinstance(v, str): v = v.replace("'", "'\"'\"'") str_envs.append(f"{k}='{v}'") str_envs = ' '.join(str_envs) return f'export {str_envs}' def _handle_command(self, command, environment): new_command = commands = '' if not self.already_init: commands = 'export SPUG_EXEC_FILE=$(mktemp)\n' commands += 'trap \'rm -f $SPUG_EXEC_FILE\' EXIT\n' self.already_init = True env_command = self._make_env_command(environment) if env_command: new_command += f'{env_command}\n' new_command += command new_command += f'\necho {self.eof} $?\n' b64_command = base64.standard_b64encode(new_command.encode()) commands += f'echo {b64_command.decode()} | base64 -di > $SPUG_EXEC_FILE\n' commands += 'source $SPUG_EXEC_FILE\n' return commands def _decode(self, content): try: content = content.decode() except UnicodeDecodeError: content = content.decode(encoding='GBK', errors='ignore') return content def __enter__(self): self.get_client() transport = self.client.get_transport() if 'windows' in transport.remote_version.lower(): self.exec_command = self.exec_command_raw self.exec_command_with_stream = self._win_exec_command_with_stream return self def __exit__(self, exc_type, exc_val, exc_tb): self.client.close() self.client = None
from linode_api4 import LinodeClient from paramiko.client import SSHClient # ssh into Linode in commandline print("-" * 100) load_dotenv() USERNAME = os.getenv(key="USERNAME") PASSWORD = os.getenv(key="PASSWORD") IP = os.getenv(key="IP") client = SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.load_system_host_keys() client.connect(hostname=IP, username=USERNAME, password=PASSWORD, look_for_keys=True) command = "cd /root & ls -1Fa" fish_shell = client.invoke_shell(term="fish") print(f"client: {client}") print(f"\nfish shell: {fish_shell}") print(f"\nexecuted command: {command}") stdin, stdout, stderr = client.exec_command(command=command) time.sleep(5) print(f"stdout: {stdout}") print(f"stdout content: {stdout.readlines()}") client.close() # accessing linode client via API print("-" * 100) TOKEN1 = os.getenv(key="TOKEN1") client = LinodeClient(token=TOKEN1)
from paramiko.client import SSHClient import time # Credentials here are for a always-on Sandbox from Cisco DevNet SSH_USER = "******" SSH_PASSWORD = "******" SSH_HOST = "<insert host>" SSH_PORT = 22 # Change this if your SSH port is differente client = SSHClient() client.load_system_host_keys() client.connect(SSH_HOST, port=SSH_PORT, username=SSH_USER, password=SSH_PASSWORD, look_for_keys=False) channel = client.get_transport().open_session() shell = client.invoke_shell() commands = ["configure terminal", "hostname test"] for cmd in commands: shell.send(cmd + "\n") out = shell.recv(1024) print(out) time.sleep(5)
class Libimobiledevice: def __init__(self): self.ssh_client = SSHClient() self.ssh_client.set_missing_host_key_policy(AutoAddPolicy()) self.ssh_client.connect(MAC_HOST_IP, port=MAC_PORT, username=MAC_USERNAME, password=MAC_PASSWORD, timeout=3) self.ssh_dict = {} def device_list(self): result = self.execute_some_command("idevice_id -l") if result.strip(): return result.strip().split('\n') else: return [] def screenshot(self, uuid): result = self.execute_some_command( f"cd {WORK_DIR};idevicescreenshot -u {uuid} {uuid}.png") result = result.replace('Screenshot saved to ', '').strip() return WORK_DIR + result def screenshot_device_info_then_upload(self, uuid, to): remote_file_path = self.screenshot(uuid) try: device_info = self.device_info(uuid) except: device_info = None file_info = self.curl_upload_file( to, remote_file_path, json.dumps(device_info, ensure_ascii=False).replace('"', '\\"')) try: file_info = json.loads(file_info).get('data') except: file_info = None return { "device_info": device_info, "file_info": file_info, } def syslog_start(self, uuid): if uuid not in self.device_list(): return False ssh = self.ssh_client.invoke_shell() ssh.send(f"cd {WORK_DIR};idevicesyslog -u {uuid}>{uuid}.txt\n") self.ssh_dict[uuid] = ssh return True def syslog_stop(self, uuid): self.ssh_dict[uuid].send(chr(3)) return WORK_DIR + uuid + '.txt' def syslog_device_info_then_upload(self, uuid, to): remote_file_path = self.syslog_stop(uuid) try: device_info = self.device_info(uuid) except: device_info = None file_info = self.curl_upload_file( to, remote_file_path, json.dumps(device_info, ensure_ascii=False).replace('"', '\\"')) try: file_info = json.loads(file_info).get('data') except: file_info = None return { "device_info": device_info, "file_info": file_info, } def device_info(self, uuid): result = self.execute_some_command(f"ideviceinfo -u {uuid}") result += self.execute_some_command( f"ideviceinfo -u {uuid} -q com.apple.disk_usage.factory") result += self.execute_some_command( f"ideviceinfo -u {uuid} -q com.apple.mobile.battery") # print(result) return { "DeviceName": re.findall('DeviceName: (.*?)\n', result, re.I)[0], "ProductType": re.findall('ProductType: (.*?)\n', result, re.I)[0], "ProductVersion": re.findall('ProductVersion: (.*?)\n', result, re.I)[0], "BatteryCurrentCapacity": re.findall('BatteryCurrentCapacity: (.*?)\n', result, re.I)[0], "BatteryIsCharging": re.findall('BatteryIsCharging: (.*?)\n', result, re.I)[0], "TotalDataCapacity": re.findall('TotalDataCapacity: (.*?)\n', result, re.I)[0], "TotalDataAvailable": re.findall('TotalDataAvailable: (.*?)\n', result, re.I)[0], } def execute_some_command(self, command): stdin, stdout, stderr = self.ssh_client.exec_command( f"bash -lc '{command}'", timeout=10) return stdout.read().decode() def ssh_logout(self): self.ssh_client.close() def curl_upload_file(self, username, filepath, device_info): result = self.execute_some_command( f'curl {DOMAIN}/api/tmt/files/ -F "file=@{filepath}" -F "username={username}" -F "device_info={device_info}"' ) if result: return result else: return "{}" def upload_file(self, local_file_path, remote_file_path): """ 上传文件 """ # 创建sftp对象上传文件 sftp = self.ssh_client.open_sftp() sftp.put(local_file_path, remote_file_path) sftp.close() def download_file(self, remote_file_path, local_file_path): """ 下载文件 """ # 创建sftp对象下载文件 sftp = self.ssh_client.open_sftp() sftp.get(remote_file_path, local_file_path) sftp.close()
class sshShell: def __init__(self, name, addr, usr, pwd, pk=None, kf=None, encoding='utf-8'): self.name, self.usr, self.pwd, self.pk, self.kf, self.encoding = name, usr, pwd, pk, kf, encoding self.host, port = addr.split(":") self.port = int(port) self.cacheStat = {} def Name(self): return self.name def __createShell(self): self.ssh = SSHClient() self.ssh.set_missing_host_key_policy(AutoAddPolicy()) self.ssh.connect(self.host, port=self.port, username=self.usr, password=self.pwd, pkey=self.pk, key_filename=self.kf, banner_timeout=3.0, auth_timeout=3.0) self.shell = self.ssh.invoke_shell() self.shell.settimeout(2.0) def __recv(self): try: return (self.shell.recv(999) or b'').decode(self.encoding) except Exception as e: return '' def __send(self, cmd): self.shell.send(cmd + '\r') def __close(self): try: self.shell.shutdown(2) except Exception as e: pass try: self.ssh.close() except Exception as e: pass def Excute(self, cmd): try: self.__createShell() print("shell hallo words: %s" % (self.__recv())) self.__send(cmd) result = '' while 1: rsp = self.__recv() if len(rsp) < 1: break result += rsp self.__close() return result except Exception as e: return traceback.format_exc() def Upload(self, files, dsDir): try: self.ssh = SSHClient() self.ssh.set_missing_host_key_policy(AutoAddPolicy()) self.ssh.connect(self.host, port=self.port, username=self.usr, password=self.pwd, pkey=self.pk, key_filename=self.kf, banner_timeout=3.0, auth_timeout=3.0) self.stftp = self.ssh.open_sftp() result = [] for f in files: if os.path.isfile(f): dir, fn = os.path.split(f) result.append((f, self.UploadFile(self.stftp, f, os.path.join(dsDir, fn)))) elif os.path.isdir(f): for root, dirs, fns in os.walk(f): for fn in fns: result.append( (os.path.join(root, fn), self.UploadFile( self.stftp, os.path.join(root, fn), os.path.join(dsDir, root.replace(f, ''), fn)))) self.__close() return True, result except Exception as e: self.__close() return False, traceback.format_exc() def UploadFile(self, sftp, local, remote): t1 = time.time() * 1000 try: # check the dir is exists remote = remote.replace("\\", "/") dir, fn = os.path.split(remote) self.check2CreateDir(sftp, dir) sftp.put(local, remote) return 'ok', time.time() * 1000 - t1 except Exception as e: return traceback.format_exc(), time.time() * 1000 - t1 def check2CreateDir(self, sftp, dir): try: dirSections = dir.split('/') if len(dir) > 0 and dir[0] == '/': dirSections[0] = '/' for i in range(len(dirSections)): pdir = '/'.join(dirSections[:i + 1]) if stat.S_ISDIR(self.cacheStat.get(pdir, 0)): continue try: a = sftp.stat(pdir) self.cacheStat[pdir] = a.st_mode if not stat.S_ISDIR(a.st_mode): return False except IOError as e: if e.errno == 2: sftp.mkdir(pdir) else: traceback.print_exc() return False except Exception as e: traceback.print_exc() return False