Python通过套接字发送命令

5 投票
4 回答
31385 浏览
提问于 2025-04-16 11:45

我遇到了一些麻烦。我想写一个简单的程序,它可以连接到服务器,执行一个命令,然后把结果返回给客户端。这听起来很简单,但我就是搞不定。目前我写的代码是这样的:

客户端:


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()

4 个回答

1

不太明白你为什么在客户端和服务器上都用 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
3

我能理解你的沮丧,Austin;我之前也遇到过同样的问题。不过,经过反复尝试,最后终于找到了办法。希望你正是想要这个:

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)
7

危险啊,威尔·罗宾逊!!!

你真的想在网络上发送没有认证的明文命令吗?这非常非常危险。

建议你使用SSH,通过paramiko来实现。

好吧,我听到这个答案太多次了。我不想用SSH,我只是想学习一下套接字。我如果想给系统发送命令,是不会用这个的。 – AustinM

从你的问题中,我可真看不出你有这么高尚的追求。:-)

套接字模块其实是对posix库的一个简单封装;使用普通的套接字编程既繁琐又容易出错。到今天为止(2014年),异步输入输出和并发并不是Python最强的特点——虽然3.4版本开始有所改善,但相关的库还需要一段时间才能跟上。我的建议是,花时间学习一些更高级的API,比如Twisted(twistedmatrix.com/trac)。如果你真的对底层的东西感兴趣,可以深入研究项目的源代码。

好的。你有什么建议可以让我用Twisted来做这种事情吗? – AustinM

可以看看twistedmatrix.com/documents/current/core/examples/#auto2

撰写回答