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 行,在 main() 文件“client.py”,第 27 行,在 main connect() 文件“client.py”,第 78 行,在连接 stdout,stderr = proc.communicate() AttributeError: 'int' object has no attribute 'communicate' 我很确定你想使用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 通过套接字发送命令的主要内容,如果未能解决你的问题,请参考以下文章

Python套接字客户端:发送数据和接收结果

python3套接字发送接收'字节'对象没有属性'读取'

通过 Java 中的套接字发送打印机命令

通过套接字发送命令,但每次都等待响应(Node.js)

通过套接字(python)发送包含文件的字典

通过套接字发送 Python 对象