如何让paramiko SSH服务器执行命令?
How to make paramiko SSH server execute cammands?
我正在尝试编写一个 SSH 服务器,一切正常,但问题似乎是我无法让客户端正常在服务器上执行命令,而且找不到正确的方法来执行此操作,因为没有提及它在文档中,看不到如何让服务器接受连接的演示示例,所以我完全迷失在这个领域。代码是:
#!/bin/python3
import paramiko
import socket
class Ctx(paramiko.server.ServerInterface):
def get_allowed_auths(self, username): return "password,publickey"
def check_auth_publickey(self, key): return paramiko.AUTH_SUCCESSFUL
def check_channel_request(self, kind, channelID): return paramiko.OPEN_SUCCEEDED
def check_channel_shell_request(self, channel): return True
def check_channel_pty_request(self, c, t, w, h, p, ph, m): return True
def get_banner(self): return ("This is MY SSH Server\n\r", "EN")
def check_channel_exec_request(self, channel, command):
print(command) # Print command
self.event.set() # I dont know why this is used.
return True # return True to accept command exec request
def check_auth_password(self, username, password):
if password == "1999": return paramiko.AUTH_SUCCESSFUL
else: return paramiko.AUTH_FAILED
paramiko.util.log_to_file("demo_server.log") # setup log file
host_key = paramiko.RSAKey(filename="./rsa") # setup rsa key file that will be used during authnitication
ctx = Ctx() # create ServerInterface context object
sock = socket.socket() # Create socket object
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 5555)) # bind socket to specific Port
sock.listen(100) # Listen for TCP connections
print("***************** Listening for connection **************************")
client, addr = sock.accept() # accept TCP socket connection
print("[+]***************** Listeing for SSH connections ***************** ")
server = paramiko.Transport(client)
server.add_server_key(host_key) # Setup key
server.start_server(server=ctx) # SSH start_server
channel = server.accept(30) # Accept Auth requests
if channel is None:
print("[+] ***************** No Auth request Was made. ***************** ")
exit(1)
channel.send("[+]***************** Welcome ***************** \n\r")
while True: # This is supposed to be used to listen to commands
channel.event.wait(5) # but I'm not sure what it does actually
正如您在 check_channel_exec_request
中的 print
语句的输出中所看到的,您正在接收一个命令名称。您只需要执行命令并将输出发送到客户端。一种实现方式可能如下所示:
def check_channel_exec_request(self, channel, command):
try:
res = subprocess.run(command, shell=True, stdout=subprocess.PIPE)
channel.send(res.stdout)
channel.send_exit_status(res.returncode)
except Exception as err:
print('exception: {}'.format(err))
channel.send('An error occurred: {}\r\n'.format(err))
channel.send_exit_status(255)
finally:
self.event.set()
return True
这里使用subprocess.run(...)
执行命令然后发送
输出到客户端。这有几个限制
实施...
- 它不是交互式的(输出直到
在命令完成后)。
- 它不处理 stderr
上的命令输出
...但希望这足以让您入门。
您的代码的另一个问题是您对
client.event
。这是一个 Python Event 对象,用于线程间的信号传递。当你写:
channel.event.wait(5)
您说的是“最多等待 5 秒以设置事件”。一个
事件由调用 event.set()
的东西设置,您可以
看看我们在 check_channel_exec_request
.
你使用这个的方式没有意义,写:
while true:
channel.event.wait(5)
你有一个无限循环。你想要的东西会等待
命令执行然后关闭通道,所以也许是什么
喜欢:
channel.event.wait(30)
channel.close()
这意味着“最多等待 30 秒让命令完成,并且
即使没有,也请关闭频道。
通过这两项更改,您的代码将接受单个命令,并且
出口。如果你想让服务器保持 运行ning 以便你可以连接
多次,你将需要实现某种循环
您代码的主要部分。
这是包含我建议的所有更改的代码:
#!/bin/python3
import paramiko
import socket
import subprocess
import time
class Ctx(paramiko.server.ServerInterface):
def get_allowed_auths(self, username):
return "password,publickey"
def check_auth_publickey(self, key):
return paramiko.AUTH_SUCCESSFUL
def check_channel_request(self, kind, channelID):
return paramiko.OPEN_SUCCEEDED
def check_channel_shell_request(self, channel):
return True
def check_channel_pty_request(self, c, t, w, h, p, ph, m):
return True
def get_banner(self):
return ("This is MY SSH Server\n\r", "EN")
def check_channel_exec_request(self, channel, command):
try:
res = subprocess.run(command, shell=True, stdout=subprocess.PIPE)
channel.send(res.stdout)
channel.send_exit_status(res.returncode)
except Exception as err:
print('exception: {}'.format(err))
channel.send('An error occurred: {}\r\n'.format(err))
channel.send_exit_status(255)
finally:
self.event.set()
return True
def check_auth_password(self, username, password):
if password == "1999": return paramiko.AUTH_SUCCESSFUL
else: return paramiko.AUTH_FAILED
paramiko.util.log_to_file("demo_server.log") # setup log file
host_key = paramiko.RSAKey(
filename="./test_rsa.key"
) # setup rsa key file that will be used during authnitication
ctx = Ctx() # create ServerInterface context object
sock = socket.socket() # Create socket object
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 5555)) # bind socket to specific Port
sock.listen(100) # Listen for TCP connections
print("***************** Listening for connection **************************")
client, addr = sock.accept() # accept TCP socket connection
print("[+]***************** Listening for SSH connections ***************** ")
server = paramiko.Transport(client)
server.add_server_key(host_key) # Setup key
server.start_server(server=ctx) # SSH start_server
channel = server.accept(30) # Accept Auth requests
if channel is None:
print("[+] ***************** No Auth request Was made. ***************** ")
exit(1)
channel.send("[+]***************** Welcome ***************** \n\r")
# wait for command execution to complete (or timeout)
channel.event.wait(30) # but I'm not sure what it does actually
channel.close()
更新 1
需要说明的是,这不会为您提供交互式会话。这让你 运行 像这样的命令:
$ ssh -p 5555 localhost date
This is MY SSH Server
lars@localhost's password:
[+]***************** Welcome *****************
Sun Aug 15 09:35:53 AM EDT 2021
Connection to localhost closed by remote host.
如果您想启用交互式会话,check_channel_exec_request
不是您想要的。
does this mean that I have to open a new channel for each command, Is this is how it's supposed to be done with SSH or I can just use the wait in loop so that only one channel for all upcoming commands.
使用 this 模型,使用 check_channel_exec_request
,每个命令都需要一个新连接。您的代码的主要部分如下所示:
while True:
print("***************** Listening for connection **************************")
client, addr = sock.accept() # accept TCP socket connection
print("[+]***************** Listening for SSH connections ***************** ")
server = paramiko.Transport(client)
[...]
当然,这不是处理事情的唯一方法,如果你看
您可以在周围找到许多基于 Paramiko 的服务示例
这可能会有所帮助。例如,ShuSSH 显示了一个重要的 Paramiko 服务器实现。
我知道你已经“提前接受”了一个答案,但你可以看看下面的内容,它基于 on SO 修改如下:
- 使用线程支持并发 SSH 请求。
- 识别用于终止程序的“退出”命令,因为处理 ctrl-C 终止的代码不太理想。设置常量
SUPPORT_EXIT = False
以移除此支持。
程序目前只是记录命令并将其回显给用户。
使用示例:
ssh localhost -p 5555 some-command
代码:
#!/usr/bin/env python
import logging
import socket
import sys
import threading
from queue import Queue
import paramiko
logging.basicConfig()
paramiko.util.log_to_file('demo_server.log', level='INFO')
logger = paramiko.util.get_logger("paramiko")
host_key = paramiko.RSAKey(filename='./rsa')
SUPPORT_EXIT = True
# input queue of requests:
in_q = Queue()
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
def check_auth_password(self, username, password):
if password == '9999':
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def get_allowed_auths(self, username):
return 'publickey,password'
def check_channel_exec_request(self, channel, command):
# This is the command we need to parse
# Here we just log it and echo it back to the user:
command = command.decode() # convert to string from bytes:
logger.info('Command = %s', command)
channel.send(command + '\n')
if SUPPORT_EXIT and command == 'exit':
# Place None in in_q to signify time to exit:
in_q.put(None)
self.event.set()
return True
def run_server(client):
t = paramiko.Transport(client)
t.set_gss_host(socket.getfqdn(""))
t.load_server_moduli()
t.add_server_key(host_key)
server = Server()
t.start_server(server=server)
# Wait 30 seconds for a command
server.event.wait(30)
t.close()
def accept(sock):
while True:
try:
client, _ = sock.accept()
except Exception as exc:
logger.error(exc)
else:
in_q.put(client)
def listener():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 5555))
sock.listen(100)
threading.Thread(target=accept, args=(sock,), daemon=True).start()
while True:
try:
client = in_q.get()
if SUPPORT_EXIT and client is None: # exit command issued
break
threading.Thread(target=run_server, args=(client,), daemon=True).start()
except KeyboardInterrupt:
sys.exit(0)
if __name__ == '__main__':
listener()
我之前的回答适合执行单个命令。此新版本支持以下变体:
ssh ip-address -p 5555 -T
- 创建交互式会话。现在,每个输入行都被回显并记录下来,直到输入 'quit\n'。
ssh ip-address -p 5555 some-command
- 执行单个命令 some-command
,但目前仅包括回显命令并记录它。
ssh ip-address -p 5555 exit
- 如果在源中设置了 SUPPORT_EXIT = True
,则关闭服务器。
#!/usr/bin/env python
import logging
import socket
import sys
import threading
from queue import Queue
import paramiko
logging.basicConfig()
paramiko.util.log_to_file('demo_server.log', level='INFO')
logger = paramiko.util.get_logger("paramiko")
host_key = paramiko.RSAKey(filename='./rsa')
SUPPORT_EXIT = True
# input queue of requests:
in_q = Queue()
def my_processor(stdin, stdout, event):
stdout.write('This is MY SSH Server:\n\n')
for command in stdin:
if command == 'quit\n':
break
# Just log the command and send it back:
logger.info('Command = %s', command)
stdout.write(command)
# signal termination
event.set()
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
def check_auth_password(self, username, password):
if password == '9999':
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def get_allowed_auths(self, username):
return 'publickey,password'
def check_channel_exec_request(self, channel, command):
# This is the command we need to parse
command = command.decode() # convert to string from bytes:
if SUPPORT_EXIT and command == 'exit':
# Place None in in_q to signify time to exit:
in_q.put(None)
# We just log it and echo it back to the user:
logger.info('Command = %s', command)
channel.send(command + '\n')
self.event.set() # Command execution complete
# Show command successfully "wired up" to stdin, stdout and stderr:
# Return False if invalid command:
return True
def check_channel_shell_request(self, channel):
""" No command specified, interactive session implied """
stdout = channel.makefile('w')
stdin = channel.makefile('r')
threading.Thread(target=my_processor, args=(stdin, stdout, self.event), daemon=True).start()
# Show command successfully "wired up" to stdin, stdout and stderr:
return True
def run_server(client):
t = paramiko.Transport(client)
t.set_gss_host(socket.getfqdn(""))
t.load_server_moduli()
t.add_server_key(host_key)
server = Server()
t.start_server(server=server)
# wait for termination:
server.event.wait()
t.close()
def accept(sock):
while True:
try:
client, _ = sock.accept()
except Exception as exc:
logger.error(exc)
else:
in_q.put(client)
def listener():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 5555))
sock.listen(100)
threading.Thread(target=accept, args=(sock,), daemon=True).start()
while True:
try:
client = in_q.get()
if SUPPORT_EXIT and client is None: # exit command issued
break
threading.Thread(target=run_server, args=(client,), daemon=True).start()
except KeyboardInterrupt:
sys.exit(0)
if __name__ == '__main__':
listener()
我正在尝试编写一个 SSH 服务器,一切正常,但问题似乎是我无法让客户端正常在服务器上执行命令,而且找不到正确的方法来执行此操作,因为没有提及它在文档中,看不到如何让服务器接受连接的演示示例,所以我完全迷失在这个领域。代码是:
#!/bin/python3
import paramiko
import socket
class Ctx(paramiko.server.ServerInterface):
def get_allowed_auths(self, username): return "password,publickey"
def check_auth_publickey(self, key): return paramiko.AUTH_SUCCESSFUL
def check_channel_request(self, kind, channelID): return paramiko.OPEN_SUCCEEDED
def check_channel_shell_request(self, channel): return True
def check_channel_pty_request(self, c, t, w, h, p, ph, m): return True
def get_banner(self): return ("This is MY SSH Server\n\r", "EN")
def check_channel_exec_request(self, channel, command):
print(command) # Print command
self.event.set() # I dont know why this is used.
return True # return True to accept command exec request
def check_auth_password(self, username, password):
if password == "1999": return paramiko.AUTH_SUCCESSFUL
else: return paramiko.AUTH_FAILED
paramiko.util.log_to_file("demo_server.log") # setup log file
host_key = paramiko.RSAKey(filename="./rsa") # setup rsa key file that will be used during authnitication
ctx = Ctx() # create ServerInterface context object
sock = socket.socket() # Create socket object
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 5555)) # bind socket to specific Port
sock.listen(100) # Listen for TCP connections
print("***************** Listening for connection **************************")
client, addr = sock.accept() # accept TCP socket connection
print("[+]***************** Listeing for SSH connections ***************** ")
server = paramiko.Transport(client)
server.add_server_key(host_key) # Setup key
server.start_server(server=ctx) # SSH start_server
channel = server.accept(30) # Accept Auth requests
if channel is None:
print("[+] ***************** No Auth request Was made. ***************** ")
exit(1)
channel.send("[+]***************** Welcome ***************** \n\r")
while True: # This is supposed to be used to listen to commands
channel.event.wait(5) # but I'm not sure what it does actually
正如您在 check_channel_exec_request
中的 print
语句的输出中所看到的,您正在接收一个命令名称。您只需要执行命令并将输出发送到客户端。一种实现方式可能如下所示:
def check_channel_exec_request(self, channel, command):
try:
res = subprocess.run(command, shell=True, stdout=subprocess.PIPE)
channel.send(res.stdout)
channel.send_exit_status(res.returncode)
except Exception as err:
print('exception: {}'.format(err))
channel.send('An error occurred: {}\r\n'.format(err))
channel.send_exit_status(255)
finally:
self.event.set()
return True
这里使用subprocess.run(...)
执行命令然后发送
输出到客户端。这有几个限制
实施...
- 它不是交互式的(输出直到 在命令完成后)。
- 它不处理 stderr 上的命令输出
...但希望这足以让您入门。
您的代码的另一个问题是您对
client.event
。这是一个 Python Event 对象,用于线程间的信号传递。当你写:
channel.event.wait(5)
您说的是“最多等待 5 秒以设置事件”。一个
事件由调用 event.set()
的东西设置,您可以
看看我们在 check_channel_exec_request
.
你使用这个的方式没有意义,写:
while true:
channel.event.wait(5)
你有一个无限循环。你想要的东西会等待 命令执行然后关闭通道,所以也许是什么 喜欢:
channel.event.wait(30)
channel.close()
这意味着“最多等待 30 秒让命令完成,并且 即使没有,也请关闭频道。
通过这两项更改,您的代码将接受单个命令,并且 出口。如果你想让服务器保持 运行ning 以便你可以连接 多次,你将需要实现某种循环 您代码的主要部分。
这是包含我建议的所有更改的代码:
#!/bin/python3
import paramiko
import socket
import subprocess
import time
class Ctx(paramiko.server.ServerInterface):
def get_allowed_auths(self, username):
return "password,publickey"
def check_auth_publickey(self, key):
return paramiko.AUTH_SUCCESSFUL
def check_channel_request(self, kind, channelID):
return paramiko.OPEN_SUCCEEDED
def check_channel_shell_request(self, channel):
return True
def check_channel_pty_request(self, c, t, w, h, p, ph, m):
return True
def get_banner(self):
return ("This is MY SSH Server\n\r", "EN")
def check_channel_exec_request(self, channel, command):
try:
res = subprocess.run(command, shell=True, stdout=subprocess.PIPE)
channel.send(res.stdout)
channel.send_exit_status(res.returncode)
except Exception as err:
print('exception: {}'.format(err))
channel.send('An error occurred: {}\r\n'.format(err))
channel.send_exit_status(255)
finally:
self.event.set()
return True
def check_auth_password(self, username, password):
if password == "1999": return paramiko.AUTH_SUCCESSFUL
else: return paramiko.AUTH_FAILED
paramiko.util.log_to_file("demo_server.log") # setup log file
host_key = paramiko.RSAKey(
filename="./test_rsa.key"
) # setup rsa key file that will be used during authnitication
ctx = Ctx() # create ServerInterface context object
sock = socket.socket() # Create socket object
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 5555)) # bind socket to specific Port
sock.listen(100) # Listen for TCP connections
print("***************** Listening for connection **************************")
client, addr = sock.accept() # accept TCP socket connection
print("[+]***************** Listening for SSH connections ***************** ")
server = paramiko.Transport(client)
server.add_server_key(host_key) # Setup key
server.start_server(server=ctx) # SSH start_server
channel = server.accept(30) # Accept Auth requests
if channel is None:
print("[+] ***************** No Auth request Was made. ***************** ")
exit(1)
channel.send("[+]***************** Welcome ***************** \n\r")
# wait for command execution to complete (or timeout)
channel.event.wait(30) # but I'm not sure what it does actually
channel.close()
更新 1
需要说明的是,这不会为您提供交互式会话。这让你 运行 像这样的命令:
$ ssh -p 5555 localhost date
This is MY SSH Server
lars@localhost's password:
[+]***************** Welcome *****************
Sun Aug 15 09:35:53 AM EDT 2021
Connection to localhost closed by remote host.
如果您想启用交互式会话,check_channel_exec_request
不是您想要的。
does this mean that I have to open a new channel for each command, Is this is how it's supposed to be done with SSH or I can just use the wait in loop so that only one channel for all upcoming commands.
使用 this 模型,使用 check_channel_exec_request
,每个命令都需要一个新连接。您的代码的主要部分如下所示:
while True:
print("***************** Listening for connection **************************")
client, addr = sock.accept() # accept TCP socket connection
print("[+]***************** Listening for SSH connections ***************** ")
server = paramiko.Transport(client)
[...]
当然,这不是处理事情的唯一方法,如果你看 您可以在周围找到许多基于 Paramiko 的服务示例 这可能会有所帮助。例如,ShuSSH 显示了一个重要的 Paramiko 服务器实现。
我知道你已经“提前接受”了一个答案,但你可以看看下面的内容,它基于
- 使用线程支持并发 SSH 请求。
- 识别用于终止程序的“退出”命令,因为处理 ctrl-C 终止的代码不太理想。设置常量
SUPPORT_EXIT = False
以移除此支持。
程序目前只是记录命令并将其回显给用户。
使用示例:
ssh localhost -p 5555 some-command
代码:
#!/usr/bin/env python
import logging
import socket
import sys
import threading
from queue import Queue
import paramiko
logging.basicConfig()
paramiko.util.log_to_file('demo_server.log', level='INFO')
logger = paramiko.util.get_logger("paramiko")
host_key = paramiko.RSAKey(filename='./rsa')
SUPPORT_EXIT = True
# input queue of requests:
in_q = Queue()
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
def check_auth_password(self, username, password):
if password == '9999':
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def get_allowed_auths(self, username):
return 'publickey,password'
def check_channel_exec_request(self, channel, command):
# This is the command we need to parse
# Here we just log it and echo it back to the user:
command = command.decode() # convert to string from bytes:
logger.info('Command = %s', command)
channel.send(command + '\n')
if SUPPORT_EXIT and command == 'exit':
# Place None in in_q to signify time to exit:
in_q.put(None)
self.event.set()
return True
def run_server(client):
t = paramiko.Transport(client)
t.set_gss_host(socket.getfqdn(""))
t.load_server_moduli()
t.add_server_key(host_key)
server = Server()
t.start_server(server=server)
# Wait 30 seconds for a command
server.event.wait(30)
t.close()
def accept(sock):
while True:
try:
client, _ = sock.accept()
except Exception as exc:
logger.error(exc)
else:
in_q.put(client)
def listener():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 5555))
sock.listen(100)
threading.Thread(target=accept, args=(sock,), daemon=True).start()
while True:
try:
client = in_q.get()
if SUPPORT_EXIT and client is None: # exit command issued
break
threading.Thread(target=run_server, args=(client,), daemon=True).start()
except KeyboardInterrupt:
sys.exit(0)
if __name__ == '__main__':
listener()
我之前的回答适合执行单个命令。此新版本支持以下变体:
ssh ip-address -p 5555 -T
- 创建交互式会话。现在,每个输入行都被回显并记录下来,直到输入 'quit\n'。ssh ip-address -p 5555 some-command
- 执行单个命令some-command
,但目前仅包括回显命令并记录它。ssh ip-address -p 5555 exit
- 如果在源中设置了SUPPORT_EXIT = True
,则关闭服务器。
#!/usr/bin/env python
import logging
import socket
import sys
import threading
from queue import Queue
import paramiko
logging.basicConfig()
paramiko.util.log_to_file('demo_server.log', level='INFO')
logger = paramiko.util.get_logger("paramiko")
host_key = paramiko.RSAKey(filename='./rsa')
SUPPORT_EXIT = True
# input queue of requests:
in_q = Queue()
def my_processor(stdin, stdout, event):
stdout.write('This is MY SSH Server:\n\n')
for command in stdin:
if command == 'quit\n':
break
# Just log the command and send it back:
logger.info('Command = %s', command)
stdout.write(command)
# signal termination
event.set()
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
def check_auth_password(self, username, password):
if password == '9999':
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def get_allowed_auths(self, username):
return 'publickey,password'
def check_channel_exec_request(self, channel, command):
# This is the command we need to parse
command = command.decode() # convert to string from bytes:
if SUPPORT_EXIT and command == 'exit':
# Place None in in_q to signify time to exit:
in_q.put(None)
# We just log it and echo it back to the user:
logger.info('Command = %s', command)
channel.send(command + '\n')
self.event.set() # Command execution complete
# Show command successfully "wired up" to stdin, stdout and stderr:
# Return False if invalid command:
return True
def check_channel_shell_request(self, channel):
""" No command specified, interactive session implied """
stdout = channel.makefile('w')
stdin = channel.makefile('r')
threading.Thread(target=my_processor, args=(stdin, stdout, self.event), daemon=True).start()
# Show command successfully "wired up" to stdin, stdout and stderr:
return True
def run_server(client):
t = paramiko.Transport(client)
t.set_gss_host(socket.getfqdn(""))
t.load_server_moduli()
t.add_server_key(host_key)
server = Server()
t.start_server(server=server)
# wait for termination:
server.event.wait()
t.close()
def accept(sock):
while True:
try:
client, _ = sock.accept()
except Exception as exc:
logger.error(exc)
else:
in_q.put(client)
def listener():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 5555))
sock.listen(100)
threading.Thread(target=accept, args=(sock,), daemon=True).start()
while True:
try:
client = in_q.get()
if SUPPORT_EXIT and client is None: # exit command issued
break
threading.Thread(target=run_server, args=(client,), daemon=True).start()
except KeyboardInterrupt:
sys.exit(0)
if __name__ == '__main__':
listener()