Выполнение туннеля s sh со скриптом Python. Ошибка: «Не удалось разрешить имя хоста при попытке открыть туннель s sh» - PullRequest
0 голосов
/ 23 апреля 2020

Здравствуйте, я работаю над простым python s sh туннельным сценарием, но я всегда получаю ошибку 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}')

1 Ответ

1 голос
/ 24 апреля 2020

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-адресе говорит о том, что он интерпретируется как символическое имя c, что облегчает определение этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...