使用Python脚本执行ssh隧道。错误:“尝试打开ssh隧道时无法解析主机名”

问题描述 投票:0回答:1

[您好,我正在使用简单的python ssh隧道scrpit,但是我一直收到Could not resolve hostname错误,但是如果手动运行它会起作用。这是我的代码:

#!/usr/bin/env python

import subprocess
import time
import tempfile

class TunnelSSH():
    def __init__(self, ssh_user: str, ssh_password: str, ssh_host: str, ssh_port: int,
                local_tunnel_port:int, remote_tunnel_host:str, remote_tunnel_port:int):
        self.ssh_user = ssh_user
        self.ssh_password = ssh_password
        self.ssh_host = ssh_host
        self.ssh_port = ssh_port
        self.local_tunnel_port = local_tunnel_port
        self.remote_tunnel_port = remote_tunnel_port
        self.remote_tunnel_host = remote_tunnel_host

        _socket_file = tempfile.NamedTemporaryFile()
        _socket_file.close()
        self.socket = _socket_file.name
        self.connected = False


    def start(self):
        ssh_conection = ['ssh', '-CN',
                        f'"{self.ssh_user}:{self.ssh_password}"@{self.ssh_host} -p {self.ssh_port}',
                        f'-L {self.local_tunnel_port}:{self.remote_tunnel_host}:{self.remote_tunnel_port}',
                        f'-S {self.socket}',
                        '-o ExitOnForwardFailure=True'
                    ]
        if not self.connected:
            status = subprocess.call(ssh_conection)
            self._check_connection(status)
            time.sleep(self.retry_sleep)
        else:
            raise Exception('Tunnel is open')

    def stop(self):
        if self.connected:
            if self._send_control_command('exit') != 0:
                raise Exception('SSH tunnel failed to exit')
            self.connected = False

    def _check_connection(self, status) -> None:
        """Check connection status and set connected to True is tunnel is open"""
        if status != 0:
            raise Exception(f'SSH tunnel failed status: {status}')
        if self._send_control_command('check'):
            raise Exception(f'SSH tunnel failed to check')
        self.connected = True

    def _send_control_command(self, ctl_cmd:str):
        call = ['ssh',f'-S {self.socket}',f'-O {self.ctl_cmd}', f'-l {self.ssh_user}', f'{self.ssh_host}']
        return subprocess.check_call(call)


if __name__ == "__main__":
    tunnel = TunnelSSH(ssh_user='...',
                        ssh_password='...',
                        ssh_host='...',
                        ssh_port=...,
                        local_tunnel_port=...,
                        remote_tunnel_host='...',
                        remote_tunnel_port=...
                    )

    retry = 10 # times
    wait_for_retry = 5 #s

    for i in range(retry):
        print(f'Connection attempt: {i}')
        try:
            tunnel.start()
        except Exception as err:
            tunnel.stop()
            print(err)
            time.sleep(wait_for_retry)

    print(f'Connected: {tunnel.connected}')
python python-3.x ssh subprocess
1个回答
1
投票

subprocess.call需要一个参数列表。形成ssh_conection时,几个参数会同时拍打,例如这部分引用为单个参数:

'"{self.ssh_user}:{self.ssh_password}"@{self.ssh_host} -p {self.ssh_port}'

修复:正确分割参数:

...
    ssh_conection = ['ssh', '-CN',
                    f'{self.ssh_user}:{self.ssh_password}@{self.ssh_host}',  # will be quoted automatically
                    '-p', f'{self.ssh_port}',
                    '-L', f'{self.local_tunnel_port}:{self.remote_tunnel_host}:{self.remote_tunnel_port}',
                    '-S', f'{self.socket}',
                    '-o', 'ExitOnForwardFailure=True'
                ]
...

提示问题的原因:IP地址直接使用。 IP地址上的“无法解析”表示该名称被解释为符号名称,这使查找起来更容易。

© www.soinside.com 2019 - 2024. All rights reserved.