2013-07-19 4 views
17

Se eseguo echo a; echo b in bash, il risultato sarà che entrambi i comandi vengono eseguiti. Tuttavia, se utilizzo il sottoprocesso, viene eseguito il primo comando, che stampa tutto il resto della riga. Il codice seguente echos a; echo b anziché a b, come ottengo che esegua entrambi i comandi?eseguendo più comandi bash con sottoprocesso

import subprocess, shlex 
def subprocess_cmd(command): 
    process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) 
    proc_stdout = process.communicate()[0].strip() 
    print proc_stdout 

subprocess_cmd("echo a; echo b") 
+1

correlato: Ecco [come eseguire più comandi di shell (ed eventualmente catturare la loro produzione) simultaneamente] (http://stackoverflow.com/a/23616229/4279) – jfs

risposta

37

devi usare shell = True nel sottoprocesso e non shlex.split:

def subprocess_cmd(command): 
    process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True) 
    proc_stdout = process.communicate()[0].strip() 
    print proc_stdout 

subprocess_cmd('echo a; echo b') 

rendimenti:

a 
b 
+1

Ah vedo, ho avuto 'shell = True' testato ma command.split() lo ha infranto (elenco). Inoltre, notare che altre persone stanno leggendo, usare 'shell = True' è un rischio per la sicurezza, assicurati di aver fiducia nell'input. – Paul

+2

Non è possibile utilizzare 'command.split()' con 'shell = True'. In realtà l'argomento di 'subprocess.Popen' con' shell = True' deve essere una stringa e non una lista. – bougui

+0

Ho trovato che questo è un po 'più semplice e non ha la confusione dell'output: def do_shell (self, command): self.proc = subprocess.Popen (command, shell = True) self.proc.wait () –

0
>>> command = "echo a; echo b" 
>>> shlex.split(command); 
    ['echo', 'a; echo', 'b'] 

così, il problema è il modulo shlex non maneggiare ";"

+0

command.split() restituisce '['echo', 'a;', 'echo', 'b']' e ha esito negativo. ' – Paul

+1

@bougui ha ragione. Imposta "shell = True", il primo argomento di Popen ha bisogno di una stringa di comando come "echo a; echo b". e senza "shell = True" il primo argomento di Popen dovrebbe essere una lista, come: ["echo", "a"] –

13

Ho appena imbattuti in una situazione in cui avevo bisogno di eseguire una serie di linee di codice bash (non separato da punto e virgola) all'interno di python. In questo scenario le soluzioni proposte non aiutano. Un approccio sarebbe quello di salvare un file e quindi eseguirlo con Popen, ma non era possibile nella mia situazione.

Quello che ho finito per fare è qualcosa di simile:

commands = ''' 
echo "a" 
echo "b" 
echo "c" 
echo "d" 
''' 

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
out, err = process.communicate(commands) 
print out 

Così ho prima creare il processo figlio bash e dopo lo dico cosa da eseguire. Questo approccio rimuove le limitazioni di passaggio del comando direttamente al costruttore Popen.

+1

'subprocess.check_output (commands, shell = True)' funziona perfettamente. Se ci sono bash-isms nei comandi, allora passa 'executable = '/ bin/bash''. – jfs

+1

Per Python 3 si potrebbe voler usare: 'out, err = process.communicate (commands.encode ('utf-8'))' e 'print (out.decode ('utf-8'))' –

4

Unire i comandi con "& &".

os.system('echo a > outputa.txt && echo b > outputb.txt') 
+1

Il secondo il comando non verrebbe eseguito se il primo comando ha un errore. Direi usare un; anziché. – NateW

1

Se stai usando solo i comandi in un solo colpo, allora si può semplicemente utilizzare subprocess.check_output funzione di convenienza:

def subprocess_cmd(command): 
    output = subprocess.check_output(command, shell=True) 
    print output