Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python sending command over a socket

I'm having a bit of trouble. I want to create a simple program that connects to the server and executes a command using subprocess then returns the result to the client. It's simple but I can't get it to work. Right now this is what I have: client:


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

server:


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()
like image 480
AustinM Avatar asked Feb 13 '11 21:02

AustinM


People also ask

How do you send multiple messages in a socket Python?

Just run the code to start the server. The server is set to recv only 2 bytes at a time for demonstration purposes (it should be something like 8192). To send data to it import it (call it shut_srv or whatever) and call send_data for the client side.

Can a socket send and receive at the same time Python?

You can send and receive on the same socket at the same time (via multiple threads). But the send and receive may not actually occur simultaneously, since one operation may block the other from starting until it's done.


3 Answers

Danger, Will Robinson!!!

Do you really want to send commands in clear text without authentication over the network? It is very, very dangerous.

Do it over SSH with paramiko.

Alright I've heard this answer too many times. I don't want to use SSH I'm just building it to learn more about sockets. I'm not going to actually use this if I want to send commands to a system. – AustinM

There is no way I could infer this noble quest from your question. :-)

The sockets module is a thin layer over the posix library; plain sockets is tedious and hard to get right. As of today (2014), asynchronous I/O and concurrency are not among Python's strongest traits - 3.4 is starting to change that but libraries will lag behind for a while. My advice is to spent your time learning some higher level API like Twisted (twistedmatrix.com/trac). If you are really interested in the low level stuff, dive in the project source.

Alright. Any idea on how I could use twisted for this type of thing? – AustinM

Look at twistedmatrix.com/documents/current/core/examples/#auto2

like image 128
Paulo Scardine Avatar answered Oct 22 '22 03:10

Paulo Scardine


Well I can understand your frustration Austin; I was in the same boat. However trial and error at last worked out. Hopefully you were looking for this:

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)
like image 26
Shoeb Lakdawala Avatar answered Oct 22 '22 03:10

Shoeb Lakdawala


It's unclear why you are using subprocess.Popen() for the same command in both the client and the server. Here's an outline of what I would try to do (pseudocode):

client

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

server

while True:
    wait for and then read command from client
    if command is "killsrv", exit
    execute command and capture output
    send output to client
like image 1
Greg Hewgill Avatar answered Oct 22 '22 02:10

Greg Hewgill