Python 通过套接字发送命令
Posted
技术标签:
【中文标题】Python 通过套接字发送命令【英文标题】:Python sending command over a socket 【发布时间】:2011-02-13 21:40:44 【问题描述】:我遇到了一些麻烦。我想创建一个连接到服务器并使用子进程执行命令然后将结果返回给客户端的简单程序。这很简单,但我无法让它工作。现在这就是我所拥有的: 客户:
import sys, socket, subprocess
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = sys.argv[1]
port = int(sys.argv[2])
socksize = 1024
conn.connect((host, port))
while True:
shell = raw_input("$ ")
conn.send(shell)
data = conn.recv(socksize)
#msglen = len(data)
output = data
iotype = subprocess.PIPE
cmd = ['/bin/sh', '-c', shell]
proc = subprocess.Popen(cmd, stdout=iotype).wait()
stdout,stderr = proc.communicate()
conn.send(stdout)
print(output)
if proc.returncode != 0:
print("Error")
服务器:
import sys, socket, subprocess
host = ''
port = 50106
socksize = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: %s" %port)
s.listen(1)
print("Now listening...\n")
conn, addr = s.accept()
while True:
print 'New connection from %s:%d' % (addr[0], addr[1])
data = conn.recv(socksize)
cmd = ['/bin/sh', '-c', data]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE).wait()
stdout,stderr = cmd.communicate()
if not data:
break
elif data == 'killsrv':
sys.exit()
【问题讨论】:
为什么不使用 paramiko 之类的东西? 是的.. 为此使用 SSH。即使使用 ssh exec 只能传递单个命令字符串 - 所以你必须注意正确引用参数。 这就是我输入命令后发生的事情。回溯(最后一次调用):文件“client.py”,第 119 行,在proc.communicate()
而不是cmd.communicate()
。此外,以明文形式发送命令似乎是一个危险的想法。你是不是在尝试做某事:trustedsec.com/files/simple_py_shell.py?
试试这个proc = Popen(data, stdout=PIPE, stderr=PIPE).wait()
stdout,stderr = proc.communicate()
@AustinM
【参考方案1】:
危险,威尔罗宾逊!!!
您真的想以明文形式发送命令而无需通过网络进行身份验证吗?这是非常非常危险的。
通过 SSH 使用 paramiko 进行操作。
好吧,这个答案我听过太多次了。我不想使用 SSH,我只是在构建它以了解有关套接字的更多信息。如果我想向系统发送命令,我不会实际使用它。 – 奥斯汀M
我无法从你的问题中推断出这个崇高的追求。 :-)
sockets 模块是 posix 库之上的一个薄层;普通的套接字很乏味,而且很难正确处理。截至今天(2014 年),异步 I/O 和并发并不是 Python 最强大的特性——3.4 开始改变这一点,但库将落后一段时间。我的建议是花时间学习一些更高级别的 API,例如 Twisted (twistedmatrix.com/trac)。如果您真的对低级的东西感兴趣,请深入研究项目源代码。
好的。关于如何将扭曲用于此类事情的任何想法? – 奥斯汀M
看twistedmatrix.com/documents/current/core/examples/#auto2
【讨论】:
好吧,这个答案我听过太多次了。我不想使用 SSH,我只是在构建它以了解有关套接字的更多信息。如果我想向系统发送命令,我不会实际使用它。 @AustinM:我的建议是花时间学习一些更高级别的 API,例如 Twisted (twistedmatrix.com/trac)。如果您真的感兴趣,请研究项目源代码。 好的。关于如何将扭曲用于此类事情的任何想法? @PauloScardine 为什么要在答案部分包含 cmets?这违背了单独 cmets 部分的目的。 @CᴴᴀZ 我喜欢在答案中引用有意义的 cmets,这样如果用户被删除,我们就不会丢失上下文。评论有些短暂,有时版主会出于某种原因将其删除。【参考方案2】:奥斯汀,我能理解你的沮丧;我在同一条船上。然而,反复试验终于奏效了。希望您正在寻找这个:
print "Command is:",command
op = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
if op:
output=str(op.stdout.read())
print "Output:",output
conn.sendall(output)
else:
error=str(op.stderr.read())
print "Error:",error
conn.sendall(error)
【讨论】:
【参考方案3】:不清楚为什么您在客户端和服务器中使用subprocess.Popen()
来执行相同的命令。这是我将尝试做的事情的概要(伪代码):
客户
while True:
read command from user
send command to server
wait for and then read response from server
print response to user
服务器
while True:
wait for and then read command from client
if command is "killsrv", exit
execute command and capture output
send output to client
【讨论】:
【参考方案4】:您的代码的问题是这一行(在客户端和服务器中):
proc = subprocess.Popen(cmd, stdout=iotype).wait()
stdout,stderr = proc.communicate()
您在Popen
对象上调用wait
,这意味着变量proc
正在获取一个int(由wait
返回)而不是Popen
对象。你可以去掉wait
——因为communicate
在返回之前等待进程结束,而且你没有检查退出代码,你不需要调用它。
然后,在您的客户端中,我认为您甚至不需要子进程调用,除非您正在运行服务器发回的某些命令。
【讨论】:
以上是关于Python 通过套接字发送命令的主要内容,如果未能解决你的问题,请参考以下文章