py.lib
2022-02-23
Parent:af2bf518950a
py.lib/ssh_tools.py
. Рефакторинг бессмысленный и беспощадный
1.1 --- a/ssh_tools.py Sat Nov 27 12:29:59 2021 +0300 1.2 +++ b/ssh_tools.py Wed Feb 23 19:27:33 2022 +0300 1.3 @@ -11,387 +11,423 @@ 1.4 HOSTKEY_warn = 1 1.5 HOSTKEY_reject = 2 1.6 1.7 -def promptChecker(user, host, buf): 1.8 - Signs = ['[', ']', '#', '<', '>', '$', '!', '%', '(', ')', '@', '+', ':', ';', ' ', '\t'] 1.9 - isPrompt = False 1.10 - isSep = True 1.11 - newLites = 0 1.12 - endBuf = '' 1.13 - for i in range(1, len(buf) + 1): 1.14 - if not isPrompt: 1.15 - if buf[-i] == '\n': 1.16 - endBuf = buf[-i] + endBuf 1.17 - continue 1.18 - isPrompt = True 1.19 - if isSep: 1.20 - if buf[-i] in Signs: 1.21 - endBuf = buf[-i] + endBuf 1.22 - continue 1.23 - isSep = False 1.24 - if buf[-i] == '\n': 1.25 - break 1.26 - _startProc = len(buf) - i 1.27 - _endProc = len(buf) - len(endBuf) 1.28 - buf = buf[_startProc:_endProc] 1.29 - searchCond = [] 1.30 - for i in [user, host]: 1.31 - bufL = '' 1.32 - bufR = '' 1.33 - index = buf.find(i) 1.34 - if index != -1: 1.35 - for ch in buf[:index][::-1]: 1.36 - if ch in Signs: 1.37 - bufL = ch + bufL 1.38 - else: 1.39 - break 1.40 - index = index + len(i) 1.41 - for ch in buf[index:]: 1.42 - if ch in Signs: 1.43 - bufR += ch 1.44 - else: 1.45 - break 1.46 - searchCond.append(bufL + i + bufR) 1.47 - 1.48 - def Check(buf): 1.49 - if buf.endswith(endBuf): 1.50 - endSearch = len(buf) - len(endBuf) 1.51 - startSearch = buf.rfind('\n', 0, len(buf) - len(endBuf)) 1.52 - 1.53 - if startSearch == -1: startSearch = 0 1.54 - 1.55 - _buf = buf[startSearch:endSearch] 1.56 - for i in searchCond: 1.57 - if _buf.find(i) == -1: return False 1.58 - return True 1.59 - else: 1.60 - return False 1.61 - return Check 1.62 - 1.63 + 1.64 +def prompt_checker(user, host, buf): 1.65 + signs = ['[', ']', '#', '<', '>', '$', '!', '%', '(', ')', '@', '+', ':', ';', ' ', '\t'] 1.66 + is_prompt = False 1.67 + is_sep = True 1.68 + end_buf = '' 1.69 + 1.70 + ch_pos = 0 1.71 + for ch_pos in range(1, len(buf) + 1): 1.72 + if not is_prompt: 1.73 + if buf[-ch_pos] == '\n': 1.74 + end_buf = buf[-ch_pos] + end_buf 1.75 + continue 1.76 + is_prompt = True 1.77 + 1.78 + if is_sep: 1.79 + if buf[-ch_pos] in signs: 1.80 + end_buf = buf[-ch_pos] + end_buf 1.81 + continue 1.82 + is_sep = False 1.83 + 1.84 + if buf[-ch_pos] == '\n': 1.85 + break 1.86 + 1.87 + _startProc = len(buf) - ch_pos 1.88 + _endProc = len(buf) - len(end_buf) 1.89 + buf = buf[_startProc:_endProc] 1.90 + search_cond = [] 1.91 1.92 -class SSHError(Exception): pass 1.93 + for ch_pos in [user, host]: 1.94 + buf_l = '' 1.95 + buf_r = '' 1.96 + index = buf.find(ch_pos) 1.97 + if index != -1: 1.98 + for ch in buf[:index][::-1]: 1.99 + if ch in signs: 1.100 + buf_l = ch + buf_l 1.101 + else: 1.102 + break 1.103 + index = index + len(ch_pos) 1.104 + for ch in buf[index:]: 1.105 + if ch in signs: 1.106 + buf_r += ch 1.107 + else: 1.108 + break 1.109 + search_cond.append(buf_l + ch_pos + buf_r) 1.110 + 1.111 + def check(check_buf): 1.112 + if check_buf.endswith(end_buf): 1.113 + end_search = len(check_buf) - len(end_buf) 1.114 + start_search = check_buf.rfind('\n', 0, len(check_buf) - len(end_buf)) 1.115 + 1.116 + if start_search == -1: 1.117 + start_search = 0 1.118 + 1.119 + _buf = check_buf[start_search:end_search] 1.120 + for i in search_cond: 1.121 + if _buf.find(i) == -1: 1.122 + return False 1.123 + 1.124 + return True 1.125 + 1.126 + else: 1.127 + return False 1.128 + 1.129 + return check 1.130 + 1.131 + 1.132 +class SSHError(Exception): 1.133 + pass 1.134 + 1.135 1.136 class TOCheck(object): 1.137 - """ 1.138 - Взято из: https://bitbucket.org/awgur/pylib/src/default/timetools.py 1.139 - """ 1.140 - def __init__(self, timeOut): 1.141 - self.start = datetime.now() 1.142 - self.timeOut = timeOut 1.143 - 1.144 - def __call__(self, timeOut=None): 1.145 - if not timeOut: 1.146 - timeOut = self.timeOut 1.147 - 1.148 - buf = datetime.now() - self.start 1.149 - 1.150 - if buf.seconds > timeOut: 1.151 - return True 1.152 - else: 1.153 - return False 1.154 - 1.155 - def __bool__(self): 1.156 - return not self(): 1.157 + """ 1.158 + Взято из: https://bitbucket.org/awgur/pylib/src/default/timetools.py 1.159 + """ 1.160 + def __init__(self, timeout): 1.161 + self.start = datetime.now() 1.162 + self.timeout = timeout 1.163 + 1.164 + def __call__(self, timeout=None): 1.165 + if not timeout: 1.166 + timeout = self.timeout 1.167 + 1.168 + buf = datetime.now() - self.start 1.169 + 1.170 + if buf.seconds > timeout: 1.171 + return True 1.172 + 1.173 + else: 1.174 + return False 1.175 + 1.176 + def __bool__(self): 1.177 + return not self() 1.178 1.179 1.180 class SSHSubsh(object): 1.181 - """Класс для облегчения работы с контекстами, когда приглашение коммандной оболочки 1.182 - меняется в результате исполнения комманды. 1.183 - """ 1.184 - def __init__(self, ssh, prompt): 1.185 - self.ssh = ssh 1.186 - self.prompt = SSHPromptCheck(prompt) 1.187 - 1.188 - def __call__(self, cmd): 1.189 - res = self.ssh(cmd, wait=False) 1.190 - res += self.waitPrompt(self.prompt) 1.191 - return res 1.192 + """Класс для облегчения работы с контекстами, когда приглашение коммандной оболочки 1.193 + меняется в результате исполнения комманды. 1.194 + """ 1.195 + def __init__(self, ssh, prompt): 1.196 + self.ssh = ssh 1.197 + self.prompt = SSHPromptCheck(prompt) 1.198 + 1.199 + def __call__(self, cmd): 1.200 + res = self.ssh(cmd, wait=False) 1.201 + res += self.waitPrompt(self.prompt) 1.202 + return res 1.203 + 1.204 1.205 class SSHPromptCheck(object): 1.206 - """ 1.207 - Проверяет, появилось ли приглашение коммандной строки в выводе сервера 1.208 - 1.209 - Принимает: 1.210 - - prompt: 1.211 - Строка, которая должна однозначно идентифицировать приглашение 1.212 - коммандной строки, либо функция которой передаётся строка, и она 1.213 - должна вернуть True, если строка завершается приглашением коммандной 1.214 - строки либо False в обратном случае. Кроме того можно передат сам объект, 1.215 - созданный заранее. 1.216 - """ 1.217 - def __init__(self, prompt): 1.218 - if isinstance(prompt, self.__class__): 1.219 - self.prompt = prompt.prompt 1.220 - self.check = prompt.check 1.221 - else: 1.222 - def isFunc(): pass 1.223 - if type(prompt) == type(isFunc): 1.224 - self.check = prompt 1.225 - self.prompt = None 1.226 - else: 1.227 - self.prompt = prompt 1.228 - 1.229 - if self.prompt == None: 1.230 - raise SSHError('Prompt not set') 1.231 - 1.232 - 1.233 - def check(self, buf): 1.234 - if buf.endswith(self.prompt): 1.235 - return True 1.236 - else: 1.237 - return False 1.238 - 1.239 - def __call__(self, buf): 1.240 - if isinstance(buf, SSHOutput): 1.241 - return self.check(buf.out) 1.242 - elif buf: 1.243 - return self.check(buf) 1.244 - else: 1.245 - return False 1.246 - 1.247 - 1.248 + """ 1.249 + Проверяет, появилось ли приглашение коммандной строки в выводе сервера 1.250 + 1.251 + Принимает: 1.252 + - prompt: 1.253 + Строка, которая должна однозначно идентифицировать приглашение 1.254 + коммандной строки, либо функция которой передаётся строка, и она 1.255 + должна вернуть True, если строка завершается приглашением коммандной 1.256 + строки либо False в обратном случае. Кроме того можно передат сам объект, 1.257 + созданный заранее. 1.258 + """ 1.259 + def __init__(self, prompt): 1.260 + if isinstance(prompt, self.__class__): 1.261 + self.prompt = prompt.prompt 1.262 + self.check = prompt.check 1.263 + 1.264 + else: 1.265 + def is_func(): 1.266 + pass 1.267 + 1.268 + if type(prompt) == type(is_func): 1.269 + self.check = prompt 1.270 + self.prompt = None 1.271 + 1.272 + else: 1.273 + self.prompt = prompt 1.274 + 1.275 + if self.prompt is None: 1.276 + raise SSHError('Prompt not set') 1.277 + 1.278 + def check(self, buf): 1.279 + if buf.endswith(self.prompt): 1.280 + return True 1.281 + 1.282 + else: 1.283 + return False 1.284 + 1.285 + def __call__(self, buf): 1.286 + if isinstance(buf, SSHOutput): 1.287 + return self.check(buf.out) 1.288 + 1.289 + elif buf: 1.290 + return self.check(buf) 1.291 + 1.292 + else: 1.293 + return False 1.294 + 1.295 + 1.296 class SSHOutput(object): 1.297 - """Содержит вывод удалённого сервера и помогает управляться с ним. 1.298 - """ 1.299 - def __init__(self, out = '', err = ''): 1.300 - self.out = out 1.301 - self.err = err 1.302 - 1.303 - 1.304 - def error(self, buf): 1.305 - "Добавить буфер к буферу сообщения об ошибке" 1.306 - self.err += buf 1.307 - 1.308 - def __add__(self, buf): 1.309 - if isinstance(buf, self.__class__): 1.310 - self.out += buf.out 1.311 - self.err += buf.err 1.312 - else: 1.313 - self.out += buf 1.314 - return self 1.315 - 1.316 - def __str__(self): 1.317 - return self.out 1.318 - 1.319 - def getError(self): 1.320 - return self.err 1.321 - 1.322 - def __bool__(self): 1.323 - if self.out or self.err: 1.324 - return True 1.325 - else: 1.326 - return False 1.327 - 1.328 - def __repr__(self): 1.329 - buf = '' 1.330 - buf += '---- OUTPUT -----------' 1.331 - buf += self.out 1.332 - buf += '---- ERRORS -----------' 1.333 - buf += self.err 1.334 - return buf 1.335 - 1.336 - def __getitem__(self, key): 1.337 - return self.out.splittines()[key] 1.338 - 1.339 - def __iter__(self): 1.340 - for line in self.out.splitlines(): 1.341 - yield line 1.342 - 1.343 - def isEol(self): 1.344 - if self.out[-1] == '\n': 1.345 - return True 1.346 - else: 1.347 - return False 1.348 - 1.349 - 1.350 + """Содержит вывод удалённого сервера и помогает управляться с ним. 1.351 + """ 1.352 + 1.353 + def __init__(self, out='', err=''): 1.354 + self.out = out 1.355 + self.err = err 1.356 + 1.357 + def error(self, buf): 1.358 + """Добавить буфер к буферу сообщения об ошибке""" 1.359 + 1.360 + self.err += buf 1.361 + 1.362 + def __add__(self, buf): 1.363 + if isinstance(buf, self.__class__): 1.364 + self.out += buf.out 1.365 + self.err += buf.err 1.366 + else: 1.367 + self.out += buf 1.368 + return self 1.369 + 1.370 + def __str__(self): 1.371 + return self.out 1.372 + 1.373 + def get_error(self): 1.374 + return self.err 1.375 + 1.376 + def __bool__(self): 1.377 + if self.out or self.err: 1.378 + return True 1.379 + else: 1.380 + return False 1.381 + 1.382 + def __repr__(self): 1.383 + buf = '' 1.384 + buf += '---- OUTPUT -----------' 1.385 + buf += self.out 1.386 + buf += '---- ERRORS -----------' 1.387 + buf += self.err 1.388 + return buf 1.389 + 1.390 + def __getitem__(self, key): 1.391 + return self.out.splittines()[key] 1.392 + 1.393 + def __iter__(self): 1.394 + for line in self.out.splitlines(): 1.395 + yield line 1.396 + 1.397 + def is_eol(self): 1.398 + if self.out[-1] == '\n': 1.399 + return True 1.400 + else: 1.401 + return False 1.402 + 1.403 + 1.404 class SSHCommunicate(object): 1.405 - """Взаимодействие с командой ssh. В сосотоянии отправлять ей данные и принимать данные от неё. 1.406 - 1.407 - Обеспчивает работу с exec_command в SSH 1.408 - """ 1.409 - def __init__(self, stdin, stdout, stderr): 1.410 - self.inC = stdin 1.411 - self.out = stdout 1.412 - self.err = stderr 1.413 - 1.414 - def __call__(self, buf=None): 1.415 - if buf != None: 1.416 - self.inC.write(buf) 1.417 - return SSHOutput(self.out.read(), self.err.read()) 1.418 - 1.419 - def __str__(self): 1.420 - return str(self()) 1.421 - 1.422 - def __repr__(self): 1.423 - return repr(self()) 1.424 + """\ 1.425 + Взаимодействие с командой ssh. В сосотоянии отправлять ей данные и принимать данные от неё. 1.426 + 1.427 + Обеспечивает работу с exec_command в SSH 1.428 + """ 1.429 + 1.430 + def __init__(self, stdin, stdout, stderr): 1.431 + self.inC = stdin 1.432 + self.out = stdout 1.433 + self.err = stderr 1.434 + 1.435 + def __call__(self, buf=None): 1.436 + if buf is not None: 1.437 + self.inC.write(buf) 1.438 + return SSHOutput(self.out.read(), self.err.read()) 1.439 + 1.440 + def __str__(self): 1.441 + return str(self()) 1.442 + 1.443 + def __repr__(self): 1.444 + return repr(self()) 1.445 + 1.446 1.447 class _SSH(object): 1.448 - """Метакласс для SSH соединений 1.449 - 1.450 - Принимает: 1.451 - - host: Имя узла 1.452 - - user: Имя пользователя 1.453 - - passwd(не обязательно, если есть key): пароль пользователя 1.454 - - key(не обязательно если есть passwd): файл ключа 1.455 - - hostKeyPol[HOSTKEY_autoAdd | HOSTKEY_warn | HOSTKEY_reject]: 1.456 - HOSTKEY_autoAdd(По умолчанию): 1.457 - если ключ удалённого узла нам неизвестен, добавить, соединение разрешить. 1.458 - HOSTKEY_warn: если ключ удалённого узла нам неизвестен, предупредить. 1.459 - HOSTKEY_reject: если ключ удалённого узла нам неизвестен, разорвать соединение. 1.460 - - timeout: таймаут операций с сервером. 1.461 - """ 1.462 - def __init__(self, host, user, passwd=None, key=None, 1.463 - hostKeyPol=HOSTKEY_autoAdd, timeout=None 1.464 - ): 1.465 - if passwd == None and key == None: 1.466 - raise SSHError('Auth type not set') 1.467 - 1.468 - if hostKeyPol == HOSTKEY_autoAdd: 1.469 - _hostKeyPol = paramiko.AutoAddPolicy() 1.470 - elif hostKeyPol == HOSTKEY_warn: 1.471 - _hostKeyPol = paramiko.WarningPolicy() 1.472 - elif hostKeyPol == HOSTKEY_reject: 1.473 - _hostKeyPol = paramiko.RejectPolicy() 1.474 - else: 1.475 - raise SSHError('Unknown policy type') 1.476 - 1.477 - self.ssh = paramiko.SSHClient() 1.478 - self.ssh.set_missing_host_key_policy(_hostKeyPol) 1.479 - if passwd: 1.480 - self.ssh.connect(hostname=host, username=user, password=passwd, look_for_keys=False, allow_agent=False) 1.481 - else: 1.482 - self.ssh.connect(hostname=host, username=user, key_filename=key, look_for_keys=False, allow_agent=False) 1.483 - 1.484 - if timeout != None: 1.485 - self.timeout = timeout 1.486 - else: 1.487 - self.timeout = TIMEOUT 1.488 - 1.489 - self.user = user 1.490 - self.host = host 1.491 - 1.492 - def __del__(self): 1.493 - try: 1.494 - self.ssh.close() 1.495 - except: 1.496 - pass 1.497 - del self.ssh 1.498 - 1.499 + """\ 1.500 + Метакласс для SSH соединений 1.501 + 1.502 + Принимает: 1.503 + - host: Имя узла 1.504 + - user: Имя пользователя 1.505 + - passwd(не обязательно, если есть key): пароль пользователя 1.506 + - key(не обязательно если есть passwd): файл ключа 1.507 + - hostKeyPol[HOSTKEY_autoAdd | HOSTKEY_warn | HOSTKEY_reject]: 1.508 + HOSTKEY_autoAdd(По умолчанию): 1.509 + если ключ удалённого узла нам неизвестен, добавить, соединение разрешить. 1.510 + HOSTKEY_warn: если ключ удалённого узла нам неизвестен, предупредить. 1.511 + HOSTKEY_reject: если ключ удалённого узла нам неизвестен, разорвать соединение. 1.512 + - timeout: таймаут операций с сервером. 1.513 + """ 1.514 + 1.515 + def __init__(self, host, user, passwd=None, key=None, 1.516 + host_key_pol=HOSTKEY_autoAdd, timeout=None 1.517 + ): 1.518 + 1.519 + if passwd is None and key is None: 1.520 + raise SSHError('Auth type not set') 1.521 + 1.522 + if host_key_pol == HOSTKEY_autoAdd: 1.523 + _hostKeyPol = paramiko.AutoAddPolicy() 1.524 + elif host_key_pol == HOSTKEY_warn: 1.525 + _hostKeyPol = paramiko.WarningPolicy() 1.526 + elif host_key_pol == HOSTKEY_reject: 1.527 + _hostKeyPol = paramiko.RejectPolicy() 1.528 + else: 1.529 + raise SSHError('Unknown policy type') 1.530 + 1.531 + self.ssh = paramiko.SSHClient() 1.532 + self.ssh.set_missing_host_key_policy(_hostKeyPol) 1.533 + if passwd: 1.534 + self.ssh.connect(hostname=host, username=user, password=passwd, look_for_keys=False, allow_agent=False) 1.535 + else: 1.536 + self.ssh.connect(hostname=host, username=user, key_filename=key, look_for_keys=False, allow_agent=False) 1.537 + 1.538 + if timeout is not None: 1.539 + self.timeout = timeout 1.540 + 1.541 + else: 1.542 + self.timeout = TIMEOUT 1.543 + 1.544 + self.user = user 1.545 + self.host = host 1.546 + 1.547 + def __del__(self): 1.548 + try: 1.549 + self.ssh.close() 1.550 + 1.551 + except: 1.552 + pass 1.553 + 1.554 + del self.ssh 1.555 + 1.556 + 1.557 class InterSSH(_SSH): 1.558 - """Класс Взаимодействия с сервером SSH 1.559 - 1.560 - Кроме аргументов необходимых для метакласса принимает: 1.561 - - prompt: 1.562 - Параметр конструктора SSHPromptCheck. Принимается строго по имени. 1.563 - """ 1.564 - def __init__(self, *a, **kwa): 1.565 - if 'prompt' in kwa: 1.566 - prompt = kwa['prompt'] 1.567 - del kwa['prompt'] 1.568 - 1.569 - _SSH.__init__(self, *a, **kwa) 1.570 - 1.571 - self.shell = self.ssh.invoke_shell() 1.572 - self.shell.settimeout(self.timeout) 1.573 - if prompt == None: 1.574 - prompt = self._getPrompt() 1.575 - self.ready = True 1.576 - else: 1.577 - self.ready = False 1.578 - self.prompt = SSHPromptCheck(prompt) 1.579 + """Класс Взаимодействия с сервером SSH 1.580 + 1.581 + Кроме аргументов необходимых для метакласса принимает: 1.582 + - prompt: 1.583 + Параметр конструктора SSHPromptCheck. Принимается строго по имени. 1.584 + """ 1.585 + def __init__(self, *a, **kwa): 1.586 + prompt = None 1.587 + if 'prompt' in kwa: 1.588 + prompt = kwa['prompt'] 1.589 + del kwa['prompt'] 1.590 + 1.591 + _SSH.__init__(self, *a, **kwa) 1.592 + 1.593 + self.shell = self.ssh.invoke_shell() 1.594 + self.shell.settimeout(self.timeout) 1.595 + if prompt is None: 1.596 + prompt = self._get_prompt() 1.597 + self.ready = True 1.598 + 1.599 + else: 1.600 + self.ready = False 1.601 + 1.602 + self.prompt = SSHPromptCheck(prompt) 1.603 1.604 - 1.605 - def __bool__(self): 1.606 - "Готово ли соединение принимать новые комманды" 1.607 - return self.ready 1.608 - 1.609 - def _getPrompt(self): 1.610 - """Возвращает объект проверки на приглашение комммандной строки из текщего 1.611 - буфера вывода. 1.612 - """ 1.613 - buf = '' 1.614 - while self.shell.recv_ready(): 1.615 - buf += self.shell.recv(1024) 1.616 - 1.617 - func = promptChecker(self.user, self.host, buf) 1.618 - return SSHPromptCheck(func) 1.619 + def __bool__(self): 1.620 + """Готово ли соединение принимать новые команды""" 1.621 + return self.ready 1.622 + 1.623 + def _get_prompt(self): 1.624 + """Возвращает объект проверки на приглашение комммандной строки из текщего 1.625 + буфера вывода. 1.626 + """ 1.627 + buf = '' 1.628 + while self.shell.recv_ready(): 1.629 + buf += self.shell.recv(1024) 1.630 + 1.631 + func = prompt_checker(self.user, self.host, buf) 1.632 + return SSHPromptCheck(func) 1.633 + 1.634 + def wait_prompt(self, prompt=None): 1.635 + """\ 1.636 + Ожидание приглашения командной строки 1.637 1.638 - 1.639 - def waitPrompt(self, prompt=None): 1.640 - """Ожидание приглашения коммандной строки 1.641 - 1.642 - Принимает необязательный аргумент: Экземпляр класса SSHPromptCheck, с помощью котороого 1.643 - проверяется присутствие приглашения командного интерпретатора в выводе. 1.644 - """ 1.645 - if prompt == None: 1.646 - prompt = self.prompt 1.647 - else: 1.648 - prompt = SSHPromptCheck(prompt) 1.649 - 1.650 - if not self.ready: 1.651 - timeCheck = TOCheck(self.timeout) 1.652 - res = SSHOutput() 1.653 - while True: 1.654 - while self.shell.recv_stderr_ready(): 1.655 - res.error(self.shell.recv_stderr(1024)) 1.656 + Принимает необязательный аргумент: Экземпляр класса SSHPromptCheck, с помощью котороого 1.657 + проверяется присутствие приглашения командного интерпретатора в выводе. 1.658 + """ 1.659 + 1.660 + if prompt is None: 1.661 + prompt = self.prompt 1.662 + 1.663 + else: 1.664 + prompt = SSHPromptCheck(prompt) 1.665 1.666 - while self.shell.recv_ready(): 1.667 - res += self.shell.recv(1024) 1.668 + res = SSHOutput() 1.669 + if not self.ready: 1.670 + time_check = TOCheck(self.timeout) 1.671 + while True: 1.672 + while self.shell.recv_stderr_ready(): 1.673 + res.error(self.shell.recv_stderr(1024)) 1.674 + 1.675 + while self.shell.recv_ready(): 1.676 + res += self.shell.recv(1024) 1.677 + 1.678 + if prompt(res): 1.679 + break 1.680 1.681 - if prompt(res): 1.682 - break 1.683 - 1.684 - if timeCheck(): 1.685 - raise SSHError('Command call timeout\n' + repr(res)) 1.686 - 1.687 - self.ready = True 1.688 - return res 1.689 + if time_check(): 1.690 + raise SSHError('Command call timeout\n' + repr(res)) 1.691 + 1.692 + self.ready = True 1.693 + return res 1.694 + 1.695 + def __call__(self, cmd, wait=True): 1.696 + """Запуск команды 1.697 + 1.698 + Принимает: 1.699 + - cmd: Комманда 1.700 + - wait(необязательный аргумент): Признак ожидания завершения комманды. 1.701 1.702 - def __call__(self, cmd, wait=True): 1.703 - """Запуск команды 1.704 - 1.705 - Принимает: 1.706 - - cmd: Комманда 1.707 - - wait(необязательный аргумент): Признак ожидания завершения комманды. 1.708 - 1.709 - Возвращает: Экземпляр класса SSHOutput 1.710 - """ 1.711 - res = SSHOutput() 1.712 - if not self.ready: 1.713 - res += self.waitPrompt() 1.714 - bytes = self.shell.send('%s\n' % cmd) 1.715 - if bytes == 0: 1.716 - raise SSHError('Channel closed') 1.717 - if wait: 1.718 - res += self.waitPrompt() 1.719 - else: 1.720 - self.ready = False 1.721 - return res 1.722 + Возвращает: Экземпляр класса SSHOutput 1.723 + """ 1.724 + res = SSHOutput() 1.725 + if not self.ready: 1.726 + res += self.wait_prompt() 1.727 + bytes = self.shell.send('%s\n' % cmd) 1.728 + if bytes == 0: 1.729 + raise SSHError('Channel closed') 1.730 + if wait: 1.731 + res += self.wait_prompt() 1.732 + else: 1.733 + self.ready = False 1.734 + return res 1.735 1.736 - def subShell(self, cmd, prompt=None): 1.737 - """Возвращает объект SSHSubsh, через который удобно работать 1.738 - интерпретаторами, запускаемыми из текущего, либо с ситуацией изменения приглашения 1.739 - командного интерпретатора. 1.740 - """ 1.741 - self(cmd, wait=False) 1.742 - if prompt == None: 1.743 - prompt = self._getPropt() 1.744 - return SSHSubsh(self, prompt) 1.745 - 1.746 - def close(self): 1.747 - res = SSHOutput 1.748 - if not self: 1.749 - res += self.waitPrompt() 1.750 - self.ssh.close() 1.751 - return res 1.752 + def sub_shell(self, cmd, prompt=None): 1.753 + """Возвращает объект SSHSubsh, через который удобно работать 1.754 + интерпретаторами, запускаемыми из текущего, либо с ситуацией изменения приглашения 1.755 + командного интерпретатора. 1.756 + """ 1.757 + self(cmd, wait=False) 1.758 + if prompt is None: 1.759 + prompt = self._getPropt() 1.760 + return SSHSubsh(self, prompt) 1.761 + 1.762 + def close(self): 1.763 + res = SSHOutput 1.764 + if not self: 1.765 + res += self.wait_prompt() 1.766 + self.ssh.close() 1.767 + return res 1.768 + 1.769 1.770 class SSH(_SSH): 1.771 - """Класс призванный управлять выполнением единичных комманд, без привлечения контекста. 1.772 - 1.773 - Принимает аргументы необходимые для метакласса _SSH 1.774 - """ 1.775 - def __init__(self, *a, **kwa): 1.776 - _SSH.__init__(self, *a, **kwa) 1.777 - 1.778 - def __call__(self, cmd): 1.779 - return SSHCommunicate(*self.ssh.exec_command(cmd, timeout=self.timeout)) 1.780 - 1.781 \ No newline at end of file 1.782 + """Класс призванный управлять выполнением единичных комманд, без привлечения контекста. 1.783 + 1.784 + Принимает аргументы необходимые для метакласса _SSH 1.785 + """ 1.786 + def __init__(self, *a, **kwa): 1.787 + _SSH.__init__(self, *a, **kwa) 1.788 + 1.789 + def __call__(self, cmd): 1.790 + return SSHCommunicate(*self.ssh.exec_command(cmd, timeout=self.timeout))