ktbyers / netmiko

Multi-vendor library to simplify Paramiko SSH connections to network devices
MIT License
3.55k stars 1.3k forks source link

huawei_telnet Unable to log in properly without a username #3480

Open mzywl opened 1 month ago

mzywl commented 1 month ago

Description of Issue/Question

Note: Please check https://guides.github.com/features/mastering-markdown/ to see how to properly format your request.

Setup

Netmiko version

(Paste verbatim output from pip freeze | grep netmiko between quotes below)

netmiko==4.4.0

Netmiko device_type (if relevant to the issue)

(Paste device_type between quotes below)

huawei_telnet

Steps to Reproduce the Issue

Error Traceback

(Paste the complete traceback of the exception between quotes below)

Pattern not detected: '(?:Change now|Please choose|[\\]>])' in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'********\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Error: The password is invalid.
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

Relevant Python code

(Please try to essentialize your Python code to the minimum code needed to reproduce the issue) (Paste the code between the quotes below)

from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'password': 'admin123',
}
connection = ConnectHandler(**device_info, timeout=10)
ktbyers commented 1 month ago
Error: The password is invalid.

It is possible that TELNET_RETURN needs to be set to \r (i.e. if you are sure that the password is correct, that is what I would experiment with). Unfortunately that is hard-coded right now (so not easily overwritten).

mzywl commented 1 month ago

Since the first time DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) is checked DEBUG:netmiko:write_channel:b'\r\n' was entered. Raise Error: The password is invalid When an ERROR is detected, it exits directly 屏幕截图 2024-08-17 123025

yearcode commented 4 weeks ago

i had rewrite telnet_login, add a dict to save netmiko sended password and username. if device respose slow, netmiko well resend password or usename. also add a method to check username_pattern, when username_pattern not found, not input username. my device is cisco

mzywl commented 4 weeks ago

i had rewrite telnet_login, add a dict to save netmiko sended password and username. if device respose slow, netmiko well resend password or usename. also add a method to check username_pattern, when username_pattern not found, not input username. my device is cisco

Where to check out the code too

yearcode commented 3 weeks ago

i had rewrite telnet_login, add a dict to save netmiko sended password and username. if device respose slow, netmiko well resend password or usename. also add a method to check username_pattern, when username_pattern not found, not input username. my device is cisco

Where to check out the code too

my rewrite code:

    def telnet_login(
            self,
            pri_prompt_terminator: str = r"#\s*$",
            alt_prompt_terminator: str = r">\s*$",
            username_pattern: str = r"(?:user:|username|login|user name|Login Name)",
            pwd_pattern: str = r"assword",
            delay_factor: Any = 30,
            max_loops: Any = 0.1,
    ) -> str:
        """Telnet login. Can be username/password or just password.

        :param pri_prompt_terminator: Primary trailing delimiter for identifying a device prompt

        :param alt_prompt_terminator: Alternate trailing delimiter for identifying a device prompt

        :param username_pattern: Pattern used to identify the username prompt

        :param delay_factor: interval seconds(间隔多少秒)

        :param max_loops: Controls the wait time in conjunction with the delay_factor
        """

        pauseTime(1)
        output = ""
        return_msg = ""
        # i = 1
        answer_key = {'password': 1, 'username': 1}
        start_time = time.time()
        while time.time() - start_time <= delay_factor:
            try:
                output = self.read_channel()
                return_msg += output

                # Search for username pattern / send username
                if answer_key['username'] and self.username is not None and self.username.strip() and re.search(
                        username_pattern, output, flags=re.I):
                    # Sometimes username/password must be terminated with "\r" and not "\r\n"
                    self.write_channel(self.username + "\r")
                    time.sleep(max_loops)
                    output = self.read_channel()
                    return_msg += output
                    answer_key['username'] = 0

                # Search for password pattern / send password
                if re.search(pwd_pattern, output, flags=re.I) and answer_key['password']:
                    # Sometimes username/password must be terminated with "\r" and not "\r\n"
                    assert isinstance(self.password, str)
                    self.write_channel(self.password + "\r")
                    time.sleep(max_loops)
                    output = self.read_channel()
                    return_msg += output
                    answer_key['password'] = 0
                    if re.search(
                            pri_prompt_terminator, output, flags=re.M
                    ) or re.search(alt_prompt_terminator, output, flags=re.M):
                        return return_msg

                # Check if proper data received
                if re.search(pri_prompt_terminator, output, flags=re.M) or re.search(
                        alt_prompt_terminator, output, flags=re.M
                ):
                    return return_msg

                # self.write_channel(self.TELNET_RETURN)
                time.sleep(max_loops)
            except EOFError:
                assert self.remote_conn is not None
                self.remote_conn.close()
                msg = f"Login failed: {self.host}"
                raise NetmikoAuthenticationException(msg)

        # Last try to see if we already logged in
        self.write_channel(self.TELNET_RETURN)
        pauseTime(max_loops)
        output = self.read_channel()
        return_msg += output
        if re.search(pri_prompt_terminator, output, flags=re.M) or re.search(
                alt_prompt_terminator, output, flags=re.M
        ):
            return return_msg

        msg = f"Login failed: {self.host}"
        assert self.remote_conn is not None
        self.remote_conn.close()
        raise NetmikoAuthenticationException(msg)
mzywl commented 3 weeks ago
def read_until_pattern(
    self,
    pattern: str = "",
    read_timeout: float = 10.0,
    re_flags: int = 0,
    max_loops: Optional[int] = None,
) -> str:
    """Read channel until pattern is detected.

    Will return string up to and including pattern.

    Returns ReadTimeout if pattern not detected in read_timeout seconds.

    :param pattern: Regular expression pattern used to identify that reading is done.

    :param read_timeout: maximum time to wait looking for pattern. Will raise ReadTimeout.
        A read_timeout value of 0 will cause the loop to never timeout (i.e. it will keep
        reading indefinitely until pattern is detected.

    :param re_flags: regex flags used in conjunction with pattern (defaults to no flags).

    :param max_loops: Deprecated in Netmiko 4.x. Will be eliminated in Netmiko 5.
    """
    if max_loops is not None:
        msg = """\n

Netmiko 4.x has deprecated the use of max_loops with read_until_pattern. You should convert all uses of max_loops over to read_timeout=x where x is the total number of seconds to wait before timing out.\n""" warnings.warn(msg, DeprecationWarning)

    if self.read_timeout_override:
        read_timeout = self.read_timeout_override

    output = ""
    loop_delay = 0.01
    start_time = time.time()
    # if read_timeout == 0 or 0.0 keep reading indefinitely
    while (time.time() - start_time < read_timeout) or (not read_timeout):
        output += self.read_channel()

        if re.search(pattern, output, flags=re_flags):
            if "(" in pattern and "(?:" not in pattern:
                msg = f"""

Parenthesis found in pattern.

pattern: {pattern}\n

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the parenthesis completely wrap the pattern '(pattern)'""" log.debug(msg) results = re.split(pattern, output, maxsplit=1, flags=re_flags)

            # The string matched by pattern must be retained in the output string.
            # re.split will do this if capturing parenthesis are used.
            if len(results) == 2:
                # no capturing parenthesis, convert and try again.
                pattern = f"({pattern})"
                results = re.split(pattern, output, maxsplit=1, flags=re_flags)

            if len(results) != 3:
                # well, we tried
                msg = f"""Unable to successfully split output based on pattern:

pattern={pattern} output={repr(output)} results={results} """ raise ReadException(msg)

            # Process such that everything before and including pattern is return.
            # Everything else is retained in the _read_buffer
            output, match_str, buffer = results
            output = output + match_str
            if buffer:
                self._read_buffer += buffer
            log.debug(f"Pattern found: {pattern} {output}")
            return output
        time.sleep(loop_delay)

    msg = f"""\n\nPattern not detected: {repr(pattern)} in output.

Things you might try to fix this:

  1. Adjust the regex pattern to better identify the terminating string. Note, in many situations the pattern is automatically based on the network device's prompt.
  2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.\n\n""" raise ReadTimeout(msg) 可以看一下这个def 的逻辑吗 我现在是 这个def 第一遍检查 ((?:user:|username|login|user name)) 后输入了\r\n 然后会报错 Error: The password times out. Password: 检查Password的时候 好像 是晚了 ? 这块有问题 我搞不明白

mzywl commented 3 weeks ago

device_info={ 'device_type': 'huawei_telnet', 'ip': '192.168.80.5', 'username': 'admin123',

} 直接把密码写在 username 就直接登录了 这块检查有问题

yearcode commented 3 weeks ago

device_info={ 'device_type': 'huawei_telnet', 'ip': '192.168.80.5', 'username': 'admin123',

} 直接把密码写在 username 就直接登录了 这块检查有问题

english: post your telnet_login's code, full code, use markdown and connect device's args, at last save session log and post here

把你的telnet_login方法完整的复制出来,不要像上面有中断的,使用markdown语法,实例化时传参是怎样的,还有session log是什么

mzywl commented 3 weeks ago

device_info={ 'device_type': 'huawei_telnet', 'ip': '192.168.80.5', 'username': 'admin123', } 直接把密码写在 username 就直接登录了 这块检查有问题

english: post your telnet_login's code, full code, use markdown and connect device's args, at last save session log and post here

把你的telnet_login方法完整的复制出来,不要像上面有中断的,使用markdown语法,实例化时传参是怎样的,还有session log是什么

我用的 是官方的 netmiko==4.4.0 没改任何代码 用断点 看到是这个 def read_until_pattern 位置的错误 断点没有断到 telnet_login方法

官方的方法

    def read_until_pattern(
        self,
        pattern: str = "",
        read_timeout: float = 10.0,
        re_flags: int = 0,
        max_loops: Optional[int] = None,
    ) -> str:
        """Read channel until pattern is detected.

        Will return string up to and including pattern.

        Returns ReadTimeout if pattern not detected in read_timeout seconds.

        :param pattern: Regular expression pattern used to identify that reading is done.

        :param read_timeout: maximum time to wait looking for pattern. Will raise ReadTimeout.
            A read_timeout value of 0 will cause the loop to never timeout (i.e. it will keep
            reading indefinitely until pattern is detected.

        :param re_flags: regex flags used in conjunction with pattern (defaults to no flags).

        :param max_loops: Deprecated in Netmiko 4.x. Will be eliminated in Netmiko 5.
        """
        if max_loops is not None:
            msg = """\n
Netmiko 4.x has deprecated the use of max_loops with read_until_pattern.
You should convert all uses of max_loops over to read_timeout=x
where x is the total number of seconds to wait before timing out.\n"""
            warnings.warn(msg, DeprecationWarning)

        if self.read_timeout_override:
            read_timeout = self.read_timeout_override

        output = ""
        loop_delay = 0.3
        start_time = time.time()
        # if read_timeout == 0 or 0.0 keep reading indefinitely
        while (time.time() - start_time < read_timeout) or (not read_timeout):
            output += self.read_channel()

            if re.search(pattern, output, flags=re_flags):
                if "(" in pattern and "(?:" not in pattern:
                    msg = f"""
Parenthesis found in pattern.

pattern: {pattern}\n

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'"""
                    log.debug(msg)
                results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                # The string matched by pattern must be retained in the output string.
                # re.split will do this if capturing parenthesis are used.
                if len(results) == 2:
                    # no capturing parenthesis, convert and try again.
                    pattern = f"({pattern})"
                    results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                if len(results) != 3:
                    # well, we tried
                    msg = f"""Unable to successfully split output based on pattern:
pattern={pattern}
output={repr(output)}
results={results}
"""
                    raise ReadException(msg)

                # Process such that everything before and including pattern is return.
                # Everything else is retained in the _read_buffer
                output, match_str, buffer = results
                output = output + match_str
                if buffer:
                    self._read_buffer += buffer
                log.debug(f"Pattern found: {pattern} {output}")
                return output
            time.sleep(loop_delay)

        msg = f"""\n\nPattern not detected: {repr(pattern)} in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.\n\n"""
        raise ReadTimeout(msg)

我的代码

 import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'password': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'********\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Error: The password is invalid.
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Password:
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

终端报错

D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\paramiko\transport.py:259: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from this module in 48.0.0.
  "class": algorithms.TripleDES,
Traceback (most recent call last):
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\huawei\huawei.py", line 199, in telnet_login
    output = self.read_until_pattern(pattern=self.prompt_or_password_change)
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\base_connection.py", line 748, in read_until_pattern
    raise ReadTimeout(msg)
netmiko.exceptions.ReadTimeout: 

Pattern not detected: '(?:Change now|Please choose|[\\]>])' in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.

二 把密码当成username传给netmiko 可以登录

import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'username': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'admin123\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
<Huawei>
DEBUG:netmiko:Pattern found: ((?:Change now|Please choose|[\]>])) :
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:Clear buffer detects data in the channel
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:
Parenthesis found in pattern.

pattern: (>|\])

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'
DEBUG:netmiko:Pattern found: (>|\]) 
<Huawei>
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:[find_prompt()]: prompt is <Huawei>
DEBUG:netmiko:prompt: Huawei
DEBUG:netmiko:In disable_paging
DEBUG:netmiko:Command: screen-length 0 temporary

DEBUG:netmiko:write_channel: b'screen-length 0 temporary\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: screen-length 0 temporary
Info: The configuration takes effect on the current user terminal interface only.
<Huawei>
DEBUG:netmiko:Pattern found: (screen\-length\ 0\ temporary) screen-length 0 temporary
DEBUG:netmiko:screen-length 0 temporary
DEBUG:netmiko:Exiting disable_paging
yearcode commented 3 weeks ago

device_info={ 'device_type': 'huawei_telnet', 'ip': '192.168.80.5', 'username': 'admin123', } 直接把密码写在 username 就直接登录了 这块检查有问题

english: post your telnet_login's code, full code, use markdown and connect device's args, at last save session log and post here 把你的telnet_login方法完整的复制出来,不要像上面有中断的,使用markdown语法,实例化时传参是怎样的,还有session log是什么

我用的 是官方的 netmiko==4.4.0 没改任何代码 用断点 看到是这个 def read_until_pattern 位置的错误 断点没有断到 telnet_login方法

官方的方法

    def read_until_pattern(
        self,
        pattern: str = "",
        read_timeout: float = 10.0,
        re_flags: int = 0,
        max_loops: Optional[int] = None,
    ) -> str:
        """Read channel until pattern is detected.

        Will return string up to and including pattern.

        Returns ReadTimeout if pattern not detected in read_timeout seconds.

        :param pattern: Regular expression pattern used to identify that reading is done.

        :param read_timeout: maximum time to wait looking for pattern. Will raise ReadTimeout.
            A read_timeout value of 0 will cause the loop to never timeout (i.e. it will keep
            reading indefinitely until pattern is detected.

        :param re_flags: regex flags used in conjunction with pattern (defaults to no flags).

        :param max_loops: Deprecated in Netmiko 4.x. Will be eliminated in Netmiko 5.
        """
        if max_loops is not None:
            msg = """\n
Netmiko 4.x has deprecated the use of max_loops with read_until_pattern.
You should convert all uses of max_loops over to read_timeout=x
where x is the total number of seconds to wait before timing out.\n"""
            warnings.warn(msg, DeprecationWarning)

        if self.read_timeout_override:
            read_timeout = self.read_timeout_override

        output = ""
        loop_delay = 0.3
        start_time = time.time()
        # if read_timeout == 0 or 0.0 keep reading indefinitely
        while (time.time() - start_time < read_timeout) or (not read_timeout):
            output += self.read_channel()

            if re.search(pattern, output, flags=re_flags):
                if "(" in pattern and "(?:" not in pattern:
                    msg = f"""
Parenthesis found in pattern.

pattern: {pattern}\n

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'"""
                    log.debug(msg)
                results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                # The string matched by pattern must be retained in the output string.
                # re.split will do this if capturing parenthesis are used.
                if len(results) == 2:
                    # no capturing parenthesis, convert and try again.
                    pattern = f"({pattern})"
                    results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                if len(results) != 3:
                    # well, we tried
                    msg = f"""Unable to successfully split output based on pattern:
pattern={pattern}
output={repr(output)}
results={results}
"""
                    raise ReadException(msg)

                # Process such that everything before and including pattern is return.
                # Everything else is retained in the _read_buffer
                output, match_str, buffer = results
                output = output + match_str
                if buffer:
                    self._read_buffer += buffer
                log.debug(f"Pattern found: {pattern} {output}")
                return output
            time.sleep(loop_delay)

        msg = f"""\n\nPattern not detected: {repr(pattern)} in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.\n\n"""
        raise ReadTimeout(msg)

我的代码

 import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'password': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'********\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Error: The password is invalid.
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Password:
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

终端报错

D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\paramiko\transport.py:259: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from this module in 48.0.0.
  "class": algorithms.TripleDES,
Traceback (most recent call last):
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\huawei\huawei.py", line 199, in telnet_login
    output = self.read_until_pattern(pattern=self.prompt_or_password_change)
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\base_connection.py", line 748, in read_until_pattern
    raise ReadTimeout(msg)
netmiko.exceptions.ReadTimeout: 

Pattern not detected: '(?:Change now|Please choose|[\\]>])' in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.

二 把密码当成username传给netmiko 可以登录

import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'username': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'admin123\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
<Huawei>
DEBUG:netmiko:Pattern found: ((?:Change now|Please choose|[\]>])) :
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:Clear buffer detects data in the channel
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:
Parenthesis found in pattern.

pattern: (>|\])

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'
DEBUG:netmiko:Pattern found: (>|\]) 
<Huawei>
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:[find_prompt()]: prompt is <Huawei>
DEBUG:netmiko:prompt: Huawei
DEBUG:netmiko:In disable_paging
DEBUG:netmiko:Command: screen-length 0 temporary

DEBUG:netmiko:write_channel: b'screen-length 0 temporary\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: screen-length 0 temporary
Info: The configuration takes effect on the current user terminal interface only.
<Huawei>
DEBUG:netmiko:Pattern found: (screen\-length\ 0\ temporary) screen-length 0 temporary
DEBUG:netmiko:screen-length 0 temporary
DEBUG:netmiko:Exiting disable_paging

从你的图片上看,有个Login authentication, 已经匹配了username_pattern, 当你把password写在username时,在telnet时,188行的第一个read_until_pattern,已经匹配到username_pattern, 然后把username发送过去,刚好就登陆成功了, 当第二个read_until_pattern时,它会读取前面发送的用户名及密码发送之后的所有当前输出,这时,匹配到password, 会发送'\r\n'(即空字符串+'\r\n'),所以,你能登陆到设备。至于你写在password时,按我上面所写,在匹配时,依然会匹配到username_pattern, write_channel写入的是'\r\n'(即空字符串+'\r\n'), 但在等待pwd_pattern时,就超时的,因为Password在前面已经出现了,后面等待不到了。

mzywl commented 3 weeks ago

device_info={ 'device_type': 'huawei_telnet', 'ip': '192.168.80.5', 'username': 'admin123', } 直接把密码写在 username 就直接登录了 这块检查有问题

english: post your telnet_login's code, full code, use markdown and connect device's args, at last save session log and post here 把你的telnet_login方法完整的复制出来,不要像上面有中断的,使用markdown语法,实例化时传参是怎样的,还有session log是什么

我用的 是官方的 netmiko==4.4.0 没改任何代码 用断点 看到是这个 def read_until_pattern 位置的错误 断点没有断到 telnet_login方法

官方的方法

    def read_until_pattern(
        self,
        pattern: str = "",
        read_timeout: float = 10.0,
        re_flags: int = 0,
        max_loops: Optional[int] = None,
    ) -> str:
        """Read channel until pattern is detected.

        Will return string up to and including pattern.

        Returns ReadTimeout if pattern not detected in read_timeout seconds.

        :param pattern: Regular expression pattern used to identify that reading is done.

        :param read_timeout: maximum time to wait looking for pattern. Will raise ReadTimeout.
            A read_timeout value of 0 will cause the loop to never timeout (i.e. it will keep
            reading indefinitely until pattern is detected.

        :param re_flags: regex flags used in conjunction with pattern (defaults to no flags).

        :param max_loops: Deprecated in Netmiko 4.x. Will be eliminated in Netmiko 5.
        """
        if max_loops is not None:
            msg = """\n
Netmiko 4.x has deprecated the use of max_loops with read_until_pattern.
You should convert all uses of max_loops over to read_timeout=x
where x is the total number of seconds to wait before timing out.\n"""
            warnings.warn(msg, DeprecationWarning)

        if self.read_timeout_override:
            read_timeout = self.read_timeout_override

        output = ""
        loop_delay = 0.3
        start_time = time.time()
        # if read_timeout == 0 or 0.0 keep reading indefinitely
        while (time.time() - start_time < read_timeout) or (not read_timeout):
            output += self.read_channel()

            if re.search(pattern, output, flags=re_flags):
                if "(" in pattern and "(?:" not in pattern:
                    msg = f"""
Parenthesis found in pattern.

pattern: {pattern}\n

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'"""
                    log.debug(msg)
                results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                # The string matched by pattern must be retained in the output string.
                # re.split will do this if capturing parenthesis are used.
                if len(results) == 2:
                    # no capturing parenthesis, convert and try again.
                    pattern = f"({pattern})"
                    results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                if len(results) != 3:
                    # well, we tried
                    msg = f"""Unable to successfully split output based on pattern:
pattern={pattern}
output={repr(output)}
results={results}
"""
                    raise ReadException(msg)

                # Process such that everything before and including pattern is return.
                # Everything else is retained in the _read_buffer
                output, match_str, buffer = results
                output = output + match_str
                if buffer:
                    self._read_buffer += buffer
                log.debug(f"Pattern found: {pattern} {output}")
                return output
            time.sleep(loop_delay)

        msg = f"""\n\nPattern not detected: {repr(pattern)} in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.\n\n"""
        raise ReadTimeout(msg)

我的代码

 import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'password': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'********\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Error: The password is invalid.
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Password:
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

终端报错

D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\paramiko\transport.py:259: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from this module in 48.0.0.
  "class": algorithms.TripleDES,
Traceback (most recent call last):
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\huawei\huawei.py", line 199, in telnet_login
    output = self.read_until_pattern(pattern=self.prompt_or_password_change)
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\base_connection.py", line 748, in read_until_pattern
    raise ReadTimeout(msg)
netmiko.exceptions.ReadTimeout: 

Pattern not detected: '(?:Change now|Please choose|[\\]>])' in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.

二 把密码当成username传给netmiko 可以登录

import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'username': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'admin123\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
<Huawei>
DEBUG:netmiko:Pattern found: ((?:Change now|Please choose|[\]>])) :
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:Clear buffer detects data in the channel
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:
Parenthesis found in pattern.

pattern: (>|\])

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'
DEBUG:netmiko:Pattern found: (>|\]) 
<Huawei>
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:[find_prompt()]: prompt is <Huawei>
DEBUG:netmiko:prompt: Huawei
DEBUG:netmiko:In disable_paging
DEBUG:netmiko:Command: screen-length 0 temporary

DEBUG:netmiko:write_channel: b'screen-length 0 temporary\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: screen-length 0 temporary
Info: The configuration takes effect on the current user terminal interface only.
<Huawei>
DEBUG:netmiko:Pattern found: (screen\-length\ 0\ temporary) screen-length 0 temporary
DEBUG:netmiko:screen-length 0 temporary
DEBUG:netmiko:Exiting disable_paging

从你的图片上看,有个Login authentication, 已经匹配了username_pattern, 当你把password写在username时,在telnet时,188行的第一个read_until_pattern,已经匹配到username_pattern, 然后把username发送过去,刚好就登陆成功了, 当第二个read_until_pattern时,它会读取前面发送的用户名及密码发送之后的所有当前输出,这时,匹配到password, 会发送'\r\n'(即空字符串+'\r\n'),所以,你能登陆到设备。至于你写在password时,按我上面所写,在匹配时,依然会匹配到username_pattern, write_channel写入的是'\r\n'(即空字符串+'\r\n'), 但在等待pwd_pattern时,就超时的,因为Password在前面已经出现了,后面等待不到了。

是的 是因为 \r\n 的问题 这应该算个bug 我没账号的时候 不要去匹配username_pattern 直接去找 Password 才对

yearcode commented 3 weeks ago

device_info={ 'device_type': 'huawei_telnet', 'ip': '192.168.80.5', 'username': 'admin123', } 直接把密码写在 username 就直接登录了 这块检查有问题

english: post your telnet_login's code, full code, use markdown and connect device's args, at last save session log and post here 把你的telnet_login方法完整的复制出来,不要像上面有中断的,使用markdown语法,实例化时传参是怎样的,还有session log是什么

我用的 是官方的 netmiko==4.4.0 没改任何代码 用断点 看到是这个 def read_until_pattern 位置的错误 断点没有断到 telnet_login方法

官方的方法

    def read_until_pattern(
        self,
        pattern: str = "",
        read_timeout: float = 10.0,
        re_flags: int = 0,
        max_loops: Optional[int] = None,
    ) -> str:
        """Read channel until pattern is detected.

        Will return string up to and including pattern.

        Returns ReadTimeout if pattern not detected in read_timeout seconds.

        :param pattern: Regular expression pattern used to identify that reading is done.

        :param read_timeout: maximum time to wait looking for pattern. Will raise ReadTimeout.
            A read_timeout value of 0 will cause the loop to never timeout (i.e. it will keep
            reading indefinitely until pattern is detected.

        :param re_flags: regex flags used in conjunction with pattern (defaults to no flags).

        :param max_loops: Deprecated in Netmiko 4.x. Will be eliminated in Netmiko 5.
        """
        if max_loops is not None:
            msg = """\n
Netmiko 4.x has deprecated the use of max_loops with read_until_pattern.
You should convert all uses of max_loops over to read_timeout=x
where x is the total number of seconds to wait before timing out.\n"""
            warnings.warn(msg, DeprecationWarning)

        if self.read_timeout_override:
            read_timeout = self.read_timeout_override

        output = ""
        loop_delay = 0.3
        start_time = time.time()
        # if read_timeout == 0 or 0.0 keep reading indefinitely
        while (time.time() - start_time < read_timeout) or (not read_timeout):
            output += self.read_channel()

            if re.search(pattern, output, flags=re_flags):
                if "(" in pattern and "(?:" not in pattern:
                    msg = f"""
Parenthesis found in pattern.

pattern: {pattern}\n

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'"""
                    log.debug(msg)
                results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                # The string matched by pattern must be retained in the output string.
                # re.split will do this if capturing parenthesis are used.
                if len(results) == 2:
                    # no capturing parenthesis, convert and try again.
                    pattern = f"({pattern})"
                    results = re.split(pattern, output, maxsplit=1, flags=re_flags)

                if len(results) != 3:
                    # well, we tried
                    msg = f"""Unable to successfully split output based on pattern:
pattern={pattern}
output={repr(output)}
results={results}
"""
                    raise ReadException(msg)

                # Process such that everything before and including pattern is return.
                # Everything else is retained in the _read_buffer
                output, match_str, buffer = results
                output = output + match_str
                if buffer:
                    self._read_buffer += buffer
                log.debug(f"Pattern found: {pattern} {output}")
                return output
            time.sleep(loop_delay)

        msg = f"""\n\nPattern not detected: {repr(pattern)} in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.\n\n"""
        raise ReadTimeout(msg)

我的代码

 import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'password': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'********\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Error: The password is invalid.
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Password:
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 

终端报错

D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\paramiko\transport.py:259: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from this module in 48.0.0.
  "class": algorithms.TripleDES,
Traceback (most recent call last):
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\huawei\huawei.py", line 199, in telnet_login
    output = self.read_until_pattern(pattern=self.prompt_or_password_change)
  File "D:\Users\admin\anaconda3\envs\ChatDev_conda_env\lib\site-packages\netmiko\base_connection.py", line 748, in read_until_pattern
    raise ReadTimeout(msg)
netmiko.exceptions.ReadTimeout: 

Pattern not detected: '(?:Change now|Please choose|[\\]>])' in output.

Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.

二 把密码当成username传给netmiko 可以登录

import logging
logging.basicConfig(filename='netmiko.log', level=logging.DEBUG)
logger = logging.getLogger("netmiko")
from netmiko import ConnectHandler
device_info={
    'device_type': 'huawei_telnet',
    'ip': '192.168.80.5',
    'username': 'admin123',

}
connection = ConnectHandler(**device_info)

日志

Login authentication

Password:
DEBUG:netmiko:Pattern found: ((?:user:|username|login|user name)) 

Login
DEBUG:netmiko:write_channel: b'admin123\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:Pattern found: (assword)  authentication

Password
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
<Huawei>
DEBUG:netmiko:Pattern found: ((?:Change now|Please choose|[\]>])) :
Info: The max number of VTY users is 5, and the number
      of current VTY users on line is 1.
      The current login time is 2024-08-23 15:08:05.
<Huawei>
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:Clear buffer detects data in the channel
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
<Huawei>
DEBUG:netmiko:
Parenthesis found in pattern.

pattern: (>|\])

This can be problemtic when used in read_until_pattern().

You should ensure that you use either non-capture groups i.e. '(?:' or that the
parenthesis completely wrap the pattern '(pattern)'
DEBUG:netmiko:Pattern found: (>|\]) 
<Huawei>
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:[find_prompt()]: prompt is <Huawei>
DEBUG:netmiko:prompt: Huawei
DEBUG:netmiko:In disable_paging
DEBUG:netmiko:Command: screen-length 0 temporary

DEBUG:netmiko:write_channel: b'screen-length 0 temporary\r\n'
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: screen-length 0 temporary
Info: The configuration takes effect on the current user terminal interface only.
<Huawei>
DEBUG:netmiko:Pattern found: (screen\-length\ 0\ temporary) screen-length 0 temporary
DEBUG:netmiko:screen-length 0 temporary
DEBUG:netmiko:Exiting disable_paging

从你的图片上看,有个Login authentication, 已经匹配了username_pattern, 当你把password写在username时,在telnet时,188行的第一个read_until_pattern,已经匹配到username_pattern, 然后把username发送过去,刚好就登陆成功了, 当第二个read_until_pattern时,它会读取前面发送的用户名及密码发送之后的所有当前输出,这时,匹配到password, 会发送'\r\n'(即空字符串+'\r\n'),所以,你能登陆到设备。至于你写在password时,按我上面所写,在匹配时,依然会匹配到username_pattern, write_channel写入的是'\r\n'(即空字符串+'\r\n'), 但在等待pwd_pattern时,就超时的,因为Password在前面已经出现了,后面等待不到了。

是的 是因为 \r\n 的问题 这应该算个bug 我没账号的时候 不要去匹配username_pattern 直接去找 Password 才对

ktbyers的环境跟我们平时的环境会存在一些差异,他的封装是比较理想化的,建议还是要自己进行重写某,类似的问题,我也遇到过不少,但从ktbyers的回复 ,有些他不觉得是bug,可以通过修改参数,当然他也提到过,如果不适用,可以重写