Python enviando comando a través de un socket

Estoy teniendo un poco de problemas. Quiero crear un progtwig simple que se conecte al servidor y ejecute un comando usando subproceso y luego devuelva el resultado al cliente. Es simple pero no puedo hacerlo funcionar. Ahora mismo esto es lo que tengo: cliente:

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

servidor:

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

Peligro, Will Robinson!

¿Realmente desea enviar comandos en texto sin cifrar a través de la red? Es muy, muy peligroso.

Hazlo por SSH con paramiko .

Muy bien, he escuchado esta respuesta demasiadas veces. No quiero usar SSH, solo lo estoy creando para aprender más sobre los sockets. No voy a usar esto realmente si quiero enviar comandos a un sistema. – AustinM

No hay forma de que pueda inferir esta noble búsqueda de tu pregunta. 🙂

El módulo de sockets es una capa delgada sobre la biblioteca de posix; Los sockets planos son tediosos y difíciles de corregir. A partir de hoy (2014), la E / S asíncrona y la concurrencia no se encuentran entre los rasgos más fuertes de Python: 3.4 está empezando a cambiar eso, pero las bibliotecas se quedarán atrás por un tiempo. Mi consejo es que dediques tu tiempo a aprender un API de nivel superior como Twisted ( twistedmatrix.com/trac ). Si está realmente interesado en las cosas de bajo nivel, sumérjase en la fuente del proyecto.

Bien. ¿Alguna idea de cómo podría usar torcido para este tipo de cosas? – AustinM

Mire twistedmatrix.com/documents/current/core/examples/#auto2

Bueno, puedo entender tu frustración Austin; Yo estaba en el mismo barco. Sin embargo, la prueba y el error finalmente funcionaron. Ojalá estuvieras buscando esto:

 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) 

No está claro por qué está utilizando subprocess.Popen() para el mismo comando tanto en el cliente como en el servidor. Aquí hay un resumen de lo que intentaría hacer (pseudocódigo):

cliente

 while True: read command from user send command to server wait for and then read response from server print response to user 

servidor

 while True: wait for and then read command from client if command is "killsrv", exit execute command and capture output send output to client 

El problema con su código es esta línea (tanto en el cliente como en el servidor):

 proc = subprocess.Popen(cmd, stdout=iotype).wait() stdout,stderr = proc.communicate() 

Está llamando a la wait en el objeto Popen , lo que significa que la variable proc está obteniendo un int (devuelto por la wait ) en lugar de un objeto Popen . Puede simplemente deshacerse de la wait , ya que la communicate espera a que finalice el proceso antes de regresar, y de todos modos no está verificando el código de salida, no necesita llamar.

Entonces, en su cliente, no creo que necesite las llamadas de subproceso, a menos que esté ejecutando algún comando que el servidor le esté enviando.