Friday, August 14, 2009

Python: parsear un fichero y cambiar el contenido de una línea

Este script crea parsea el fichero de configuración del apache2 en la ruta que le indiquemos y substituye el DocumentRoot del VirtualHost que le indiquemos por uno nuevo que también le pasamos por parámetro:

./scriptillo.py <ruta_al_fichero_de_configuración> <VirtualHost> <nueva_ruta>

El contenido del fichero es:


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from cStringIO import StringIO
import re

# r'<VirtualHost\s(.*?)>' significa cadena de tipo raw
# que coincide con <VirtualHost más cualquier cadena de espacios
# tabuladores ... lo que sea más cualquier carácter que no sea fin de línea
# o ninguno, y acabe en >
vhost_start = re.compile(r'<VirtualHost\s(.*?)>')
vhost_end = re.compile(r'</VirtualHost')
# r'(DocumentRoot\s+)(\S+)' significa cadena de tipo raw
# (DocumentRoot\s+) significa que cumple que tiene DocumentRoot más una
# o más espacios o similar; y además lo anterior va seguido de una cadena
# diferente de espacios en blanco.
docroot_re = re.compile(r'(DocumentRoot\s+)(\S+)')

def replace_docroot(conf_string, vhost, new_docroot):
'''yield new lines of an httpd.conf file where docroot lines matching
the specified vhost are replaced with the new_docroot
'''
conf_file = StringIO(conf_string)
# variable que controla si estamos en el VirtualHost correcto
in_vhost = False
# Inicializamos curr_vhost como objeto
curr_vhost = None
for line in conf_file :
# comprobamos si la línea es del tipo <VirtualHost ...>
vhost_start_match = vhost_start.search(line)
# Si lo es, asignamos curr_vhost el nombre al que
# responde el VirtualHost:<puerto> que estamos leyendo
if vhost_start_match :
curr_vhost = vhost_start_match.groups()[0]
in_vhost = True
# Si estamos en un VirtualHost y es el que le hemos indicado
# empezamos a buscar la línea de DocumentRoot y hacemos la substitución
if in_vhost and (curr_vhost == vhost) :
doc_root_match = docroot_re.search(line)
if doc_root_match :
sub_line = docroot_re.sub(r'\1%s' % new_docroot, line)
line = sub_line
# Comprobamos si hemos llegado al final del VirtualHost
# y si es así reseteamos la variable in_vhost
vhost_end_match = vhost_end.search(line)
if vhost_end_match :
in_vhost = False
yield line

if __name__=='__main__' :
import sys
# fichero de configuración de apache2
conf_file = sys.argv[1]
# VirtualHost cuyo DocumentRoot hay que modificar
vhost = sys.argv[2]
# nuevo DocumentRoot
docroot = sys.argv[3]

# leemos del fichero de configuración
conf_string = open(conf_file).read()
# para cada línea llamamos a la función encargada de hacer la
# substitución si es necesario
for line in replace_docroot(conf_string,vhost,docroot):
print line

No comments: