viernes, 20 de julio de 2012

subprocess en python

Vamos a ver cómo hacer un script de parada/arranque de un servicio utilizando subprocess.

subprocess nos va a permitir lanzar un comando y esperar a que este termine, y una vez terminado, ver en qué estado ha finalizado.

El siguiente ejemplo se puede utilizar para llevar a cabo un reinicio automático de un servicios (jboss por ejemplo) y estar seguros de que el servicio es detenido y arrancado correctamente:

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import subprocess
script_arranque='/etc/init.d/jboss start'
script_parada='/etc/init.d/jboss stop'
#paramos jboss
pipe=subprocess.Popen(script_arranque, stdout=subprocess.PIPE, shell=True)
estado=pipe.wait()
out, err = pipe.communicate()
if estado == 0:
        print "Estado salida correcto."
else:
        print "Salida de error: " + str(err) 
'''en este caso, el único proceso java que corre es jboss, si hubiese más de uno, la siguiente opción no sería válida ' ' '
pipe=subprocess.Popen('pidof java', stdout=subprocess.PIPE, shell=True)
out, err = pipe.communicate()
pid = out.strip()
if pid != '':
        print "El proceso no se ha detenido, matamos el pid: " + pid + "."
        pipe=subprocess.Popen('kill -9 ' + pid, stdout=subprocess.PIPE, shell=True)
#Ya está parado jboss, ahora lo arrancamos
pipe=subprocess.Popen(script_parada, stdout=subprocess.PIPE, shell=True)
estado=pipe.wait()
out, err = pipe.communicate()
if estado == 0:
        print "Estado salida correcto."
else:
        print "Salida de error: " + str(err)


Un detalle a tener en cuenta cuando utilicemos subprocess es que si utilizamos la shell (shell=True) el comando que pasemos será una cadena, mientras que si no utilizamos la shell (shell=False) el comando se ha de pasar como una lista. Por ejemplo, para ejecutar un ls -la:

Con shell:
    subprocess.Popen('ls -la', shell=True)
Sin shell:
    subprocess.Popen(['ls','-la'], shell=False)


Para ver el estado en el que finaliza, podemos hacerlo mediante:

estado=pipe.wait()

ó

estado=pipe.returncode


Y para ver la salida estándar y la salida de error, haremos uso de communicate:

out, err = pipe.communicate()

Envío de correo en python bajo SSL

Si necesitáis enviar correos con python por ssl de una forma sencilla, recomiendo el uso de pyzmail (http://www.magiksys.net/pyzmail/). Para instalar pyzmail, lo podéis hacer directamente con pip:

pip install pyzmail

Si no tenemos instalado pip, para instalarlo:

wget http://python-distribute.org/distribute_setup.py 
python distribute_setup.py 
easy_install pip

Os dejo un sencillo código de ejemplo:

# -*- coding: iso-8859-15 -*- import pyzmail #Componemos el correo sender=('Yo','cuenta@remitente.es') recipients=['cuenta@destinatario.es',] subject='Prueba envio SSL' text_content='Este correo ha sido enviado bajo SSL' prefered_encoding='iso-8859-1' text_encoding='iso-8859-1' #Vamos a adjuntar dos ficheros fichero=open('fichero.txt.tar.gz', 'rb').read() fichero2=open('fichero.txt','rb').read() payload, mail_from, rcpt_to, msg_id=pyzmail.compose_mail( sender, recipients, subject, prefered_encoding, (text_content, text_encoding), html=None, attachments=[(fichero, 'application', 'octet-stream', 'fichero.tar.gz', 'us-ascii'),(fichero2, 'application', 'octet-stream', 'fichero.txt', 'us-ascii')]) #Datos de configuracion para el envio smtp_host='host' smtp_port=puerto para comunicacion ssl smtp_mode='ssl' smtp_login='cuenta@remitente.es' smtp_passwd='password' #Enviamos el correo ret=pyzmail.send_mail(payload, mail_from, rcpt_to, smtp_host, smtp_port=smtp_port, smtp_mode=smtp_mode, smtp_login=smtp_login, smtp_password=smtp_passwd) if isinstance(ret, dict): if ret: print 'fallo en los destinatario:', ', '.join(ret.keys()) else: print 'correcto' else: print 'error:', ret

Obtener informacion de repositorios a través de los metadatos .git publicados por error

 A raiz de CTF realizado recientemente, me ha parecido interesante publicar este post sobre los errores de seguridad que se encuentran en mu...