fgimian / paramiko-expect

A Python expect-like extension for the Paramiko SSH library which also supports tailing logs.
MIT License
204 stars 78 forks source link

Unsupported operand type(s), line 164 in expect #74

Open apaxson opened 3 years ago

apaxson commented 3 years ago

Currently executing a multiple expect option. The code is:

ssh_client = SSHClientInteraction(remote_conn_pre, timeout=10, display=True)
# ... STUFF
i = ssh_client.expect(".* ERROR .*$", "Restarting the system\.{3}\s*")

This is where I'm determining if my sent command ends in an error, or the correct "restart". When the code executes, I get the following traceback:

Traceback (most recent call last):
  File "/Users/apax/Devel/ssh_cmd_EDA/ssh_interact.py", line 45, in <module>
    i = ssh_client.expect(".* ERROR .*$", "Restarting the system\.{3}\s*")
  File "/Users/apax/Library/Python/3.8/lib/python/site-packages/paramiko_expect.py", line 164, in expect
    if time.time() >= (base_time + timeout):
TypeError: unsupported operand type(s) for +: 'float' and 'str'

I can't imagine a time where "timeout" would ever be a string? If I remove the multiple expect options, it runs through fine. This is using version 0.3.0

zebbarry commented 3 years ago

expect takes restrings as a single string or list of strings, as you have provided a string for the first argument, the second argument is used to set the timeout for the expect (expect definition). This is what causes the TypeError as the timeout is set to a string.

def expect(
        self, re_strings='', timeout=None, output_callback=None, default_match_prefix='.*\n',
        strip_ansi=True, ignore_decode_error=True
    ):

To fix this issue expect should be used with the re-strings as a list in the first argument like this:

i = ssh_client.expect([".* ERROR .*$", "Restarting the system\.{3}\s*"])
apaxson commented 3 years ago

Thank you. Putting it as a list did execute normally, (my apologies for not looking at code), but it is not matching the current_output and timing out, though, doing an re.compile().match(default_match_prefix + re_string + '$", SSHClientInteraction.current_output, re.DOTALL) against current_output returns with an object.

However, the code still times out. It looks like current_buffer_output_decoded is always an empty string? I may have missed it, but I don't see where this value gets updated prior to the loop for regex matching.

https://github.com/fgimian/paramiko-expect/blob/c47b7843c73f804284d32f1a3b3e2c0b498760bd/paramiko_expect.py#L143

apaxson commented 3 years ago

updated the code to:

current_buffer_output_decoded = self.current_output_clean

matches correctly.

fruch commented 2 years ago

Thank you. Putting it as a list did execute normally, (my apologies for not looking at code), but it is not matching the current_output and timing out, though, doing an re.compile().match(default_match_prefix + re_string + '$", SSHClientInteraction.current_output, re.DOTALL) against current_output returns with an object.

However, the code still times out. It looks like current_buffer_output_decoded is always an empty string? I may have missed it, but I don't see where this value gets updated prior to the loop for regex matching.

https://github.com/fgimian/paramiko-expect/blob/c47b7843c73f804284d32f1a3b3e2c0b498760bd/paramiko_expect.py#L143

It gets updated in the last line of the loop