2012-10-23 26 views
8

Sto lavorando su alcuni script (nell'azienda in cui lavoro) che vengono caricati/scaricati in hypervisor per sparare un pezzo di codice quando si verifica un evento. L'unico modo per scaricare effettivamente uno script è premere Ctrl - C. Sto scrivendo una funzione in Python che automatizza il processoSimula l'interrupt di tastiera Ctrl-C in Python mentre si lavora in Linux

Non appena vede la stringa "done" nell'output del programma, dovrebbe uccidere lo vprobe. Sto usando subprocess.Popen per eseguire il comando:

lineList = buff.readlines() 
cmd = "vprobe /vprobe/myhello.emt" 
p = subprocess.Popen(args = cmd, shell=True,stdout = buff, universal_newlines = True,preexec_fn=os.setsid) 
while not re.search("done",lineList[-1]): 
     print "waiting" 
os.kill(p.pid,signal.CTRL_C_EVENT) 

Come potete vedere, sto scrivendo l'uscita in buff descrittore di file aperto in lettura + modalità di scrittura. Controllo l'ultima riga; se ha 'done', lo uccido. Sfortunatamente, lo CTRL_C_EVENT è valido solo per Windows. Cosa posso fare per Linux?

+3

FYI: 're.search' con una stringa costante può essere meglio espresso in' po 'fatto' non in linelist [-1]: ... ' – nneonneo

+0

Sì, hai ragione. Grazie. –

risposta

8

Penso che si possa semplicemente inviare l'equivalente Linux, signal.SIGINT (il segnale di interruzione).

(Modifica: avevo qualcosa qui scoraggiante l'uso di questa strategia per il controllo dei sottoprocessi, ma su una lettura più attenta sembra che tu abbia già deciso che hai bisogno di controllo-C in questo caso specifico ... Quindi, SIGINT dovrebbe farlo.)

+0

hey Andrew. Grazie per la risposta. Ma in realtà, SIGINT uccide solo la funzione di sottoprocesso mentre il vprobe continua la sua esecuzione. Hai un'idea di come ucciderlo anche tu? Grazie –

+1

Beh, se funziona su Windows, speriamo che questo significhi che il segnale sta andando nel posto giusto. Quindi, prova qualcosa di più forte. Prova SIGTERM e, se ciò non funziona, SIGKLL. Se SIGKILL non funziona, allora non sarà necessario - dovrai esaminare diversi modi di gestire il sottoprocesso del tutto. –

+0

Hai provato 'Popen (['vprobe', '/vprobe/myhello.emt'], shell = False, ...)'? @Core_Dumped – alk

1

Forse ho frainteso qualcosa, ma il modo in cui lo fai è difficile ottenere il risultato desiderato.

Qualunque sia lo buff, lo si interroga prima, quindi lo si utilizza nel contesto di Popen() e quindi si spera che per maciv lineList si riempia automaticamente.

Che probabilmente si desidera è qualcosa di simile

logfile = open("mylogfile", "a") 
p = subprocess.Popen(['vprobe', '/vprobe/myhello.emt'], stdout=subprocess.PIPE, buff, universal_newlines=True, preexec_fn=os.setsid) 
for line in p.stdout: 
    logfile.write(line) 
    if re.search("done", line): 
     break 
    print "waiting" 
os.kill(p.pid, signal.CTRL_C_EVENT) 

Questo vi dà un'estremità del tubo alimentato dallo script vprobe che potete leggere fuori formato da linee e agire in modo appropriato sulla uscita trovata.

+0

Questo è quasi esattamente quello che voglio fare, tranne che voglio che l'output venga stampato anche in alcuni file (insieme a entrare nel PIPE per scopi di controllo). Come lo posso fare? (Spero di essere grammaticalmente corretto questa volta :)) –

+0

Ho modificato la mia risposta per aver fornito un modo per farlo. – glglgl

+0

Il codice sopra sembra buono e buono ma quando uso lo stdout come attributo dell'oggetto p, mi dà errore PIPE rotto. –

3

In Linux, l'interrupt di tastiera Ctrl-C può essere inviato programmaticamente a un processo utilizzando la funzione Popen.send_signal (signal.SIGINT). Per esempio

import subprocess 
import signal 

.. 
process = subprocess.Popen(..) 
.. 
process.send_signal(signal.SIGINT) 
.. 

Non utilizzare Popen.communicate() per i comandi di blocco ..

Problemi correlati