Я соединил веб-браузер с stdin
и stdout
команды, работающей на удаленном конце соединения SSH. Похоже, вы пытаетесь сделать что-то подобное: подключите сокет к программе, запущенной на удаленной машине, чтобы клиенты могли подключиться к хосту/порту и использовать указанную удаленную программу.
Первое, что вам нужно сделать, это установить соединение SSH. Я использую внешнюю программу ssh
(либо ssh
, либо plink
в зависимости от ОС) в подпроцессе. Для этого вы можете просто использовать класс subprocess.Popen
. Подпроцесс запускает (внешнее) приложение ssh
для подключения к удаленному хосту и выполняет требуемую команду. Затем он сидит, слушая его «stdin» и желая ответить на его «stdout».
(Вы могли бы использовать реализацию SSH Python, такие как Paramiko здесь)
На очень высоком уровне (где remote_command
является вещь, чтобы работать на дальнем конце):
import subprocess
command = ['ssh', '[email protected]', 'remote_command']
sproc = subprocess.Popen(command, shell=False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
Это дает вам подпроцесс, с которым вы можете взаимодействовать через его stdin
, stdout
и stderr
.
Получите этот бит в первую очередь.
Следующее, что вам нужно - это связать сокет, прослушать и принять соединение. Затем читайте с клиента и пишите на сервер. Я написал легкий Socat
(вдохновленный Socat) класс:
import socket
class Socat(object):
EOT = '\004\r\n'
def __init__(self, binding, stream, eot = EOT):
self.stream = stream
self.eot = eot
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(binding)
self.socket.listen(5)
while True:
print "waiting for connection"
(clientsocket, address) = self.socket.accept()
print "connection from %s:%s" % address
data = clientsocket.recv(1024)
self.stream.write(data)
while data:
data = self.stream.readline()
if data:
print "read %s bytes" % len(data)
if data == self.eot:
print "read termination signature"
clientsocket.close()
data = None
else:
clientsocket.send(data)
Вы должны прочитать на Sockets: this и this полезны здесь.
Вы можете использовать это, чтобы подключиться к remote_command
:
Socat(('localhost', 8080), sproc)
Есть некоторые недостающие биты
Вы заметите socat
класс занимает в stream
(в отличие от моего примера), что имеет методы write
и readline
. Я фактически инкапсулировал соединение SSH в классе, но я оставлю это как упражнение для читателя!
(В основном class Stream
, который содержит sproc
и обеспечивает write
и readline
методы - эффективно sproc.stdin.write()
и sproc.stdout.readline()
- вы получите идею)
Кроме того, вам нужен протокол, чтобы remote_command
сигнализировать конец передачи , Я использовал символ ASCII EOT
, и моя удаленная программа отправляет его в конце ответа. socat
использует это, чтобы закрыть клиентское соединение и принять новый. В зависимости от вашего прецедента вам понадобится протокол, который будет работать для вас.
Наконец
Все перечисленные выше, могут быть улучшены. То, что выше, - это мой первый разрез, потому что просто видеть внутреннюю работу. С тех пор я расширил его, чтобы запустить цикл принятия в потоке и изящно обрабатывать разъединения и так далее.
Но, надеюсь, что выше, является разумной отправной точкой.
То, что вы пытаетесь сделать, вполне разумно. Вы можете изучить модуль 'pexpect'. Он предназначен для такого рода вещей: вождение интерактивного приложения. См. Https://pexpect.readthedocs.io/en/stable/overview.html для хорошего старта. Он также имеет возможность устанавливать таймауты в ваших взаимодействиях в случае, если вы ожидаете ответа, но не получите его. –