• Publicidad

Script para crear subdominios automaticamente

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Script para crear subdominios automaticamente

Notapor cmp » 2009-07-23 12:08 @547

Hola a todos.

Estoy escribiendo un script para poder crear subdominios de forma automática así como un pequeño espacio web.

No tengo muy claro si va a Avanzado...

La idea es la siguiente: un usuario del sitio, con solo rellenar un formulario con el nombre del subdominio deseado y su e-mail tenga listo en un momento su subdomino.

De Perl se lo justo y de momento tengo esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use File::Copy;
  4.  
  5. #perl genera_dominio.pl  NOMBRE_SUBDOMINIO  E-MAIL
  6.  
  7. my $nom_dom = $ARGV[0]; #p.e. nom que el usuario quiere para subdominio
  8. my $sites_apache = "/etc/apache2/sites-available"; la
  9. my $ruta = "$sites_apache/$nom_dom";
  10. my $mail = $ARGV[1]; #recogemos el e-mail del usuario
  11. my $dominio = "www.$nom_dom.dominio.com";
  12. my $ubicacion = "/var/www/$nom_dom";
  13. my $log_error = "/var/log/apache2/error_$nom_dom.log";
  14. my $log_custom = "/var/log/apache2/access_$nom_dom.log";
  15.  
  16. #Creamos el nuevo fichero de configuración
  17. #Comprobamos que no exista ya
  18. if (-e "$sites_apache/$nom_dom") {
  19.     print "El nombre de subdominio $nom_dom ja existe ! \n";
  20. }
  21. else {
  22.  
  23.   #Tenemos una plantilla con los valores clave a cambiar
  24.   copy("$sites_apache/plantilla", "$sites_apache/$nom_dom") or die "No se pudo copiar el fichero: $!";
  25.  
  26.   #Colocar valor de escape delante de '@' para que funcione bien
  27.   #valor a sustituir =~ s/patrón de búsqueda/patrón de sustitución/opciones
  28.   my $mail_arroba = "$mail";
  29.   $mail_arroba =~ s/@/\\@/;
  30.  
  31.   #Buscamos los valores a sustituir en el fichero /etc/apache2/sites-available/$nom_dom
  32.   system("perl -p -i -e 's/EMAIL/$mail_arroba/g;' $ruta");
  33.   system("perl -p -i -e 's/DOMINIO/$dominio/g;' $ruta");
  34.   system("perl -p -i -e 's {UBICACION} {$ubicacion}g;' $ruta");
  35.   system("perl -p -i -e 's {LOG_ERROR} {$log_error}g;' $ruta");
  36.   system("perl -p -i -e 's {LOG_CUSTOM} {$log_custom}g;' $ruta");
  37.  
  38.   #Añadimos el subdominio en /etc/hosts para simular DNS a nivel local
  39.   system("perl -p -i -e 's/#AÑADIR_DOM_AQUI/$dominio #AÑADIR_DOM_AQUI/;' /etc/hosts");
  40.  
  41.   #Activamos (enable) el nuevo Vhost
  42.   system("cd $sites_apache");
  43.   system("sudo a2ensite $nom_dom");
  44.  
  45.   #Creamos el directorio para el nuevo site
  46.   mkdir "/var/www/$nom_dom", 0755 or warn"No se pudo crear el directorio: $!";
  47.   #Creamos un index.html para que se muestre algo hasta que el usuario ponga su contenido
  48.   open(fd,">/var/www/$nom_dom/index.html") or die "No se pudo crear el fichero index.html\n";  
  49.   print fd "<title>$dominio</title> <html>Espacio web $nom_dom</html>";
  50.   close(fd);
  51.  
  52.   #Reiniciamos apache para que los cambios tengan efecto
  53.   system("sudo /etc/init.d/apache2 reload");
  54.  
  55.   #Para las pruebas
  56.   print "\n-------------------\nSe creó el dominio $dominio con exito! \n";
  57.   print "Correo electronico: $mail \n";
  58.   print "El log de errores : $log_error \n";
  59.   print "El log de accesos : $log_custom \n-------------------\n";
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Como podéis ver utilizo la técnica de buscar patrones en una plantilla prediseñada para poner los datos adecuados para cada usuario. No sé si hay alguna forma más elegante o eficaz pero no se me ha ocurrido...

¿Es una buena opción hacerlo en Perl?

Me gustaría que me dierais vuestra opinión y cosas a mejorar/cambiar, etc... o directamente si es una barbaridad XD
cmp
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2007-05-28 10:43 @488

Publicidad

Re: Script para crear subdominios automaticamente

Notapor explorer » 2009-07-23 14:46 @657

Unos comentarios rápidos...

* Te recomiendo la lectura del módulo Text::Template. Vete a la parte de la descripción, al ejemplo que trae. Verás que el uso de plantillas simplifica bastante tu código y te ahorra todas las llamadas "perl -p -i -e".

* Para añadir un dominio al final de un fichero de texto, te vale con abrir el fichero en modo añadir ('>>'). Si, en cambio estás añadiendo en una determinada línea, el uso de Tie::File permite mapear el fichero de texto a un arreglo, con lo que localizar, cambiar y grabar la línea es muy sencillo (5 líneas). A cambio, te ahorras otra llamada a un proceso externo, que siempre es algo muy costoso para el sistema operativo.

* De la parte
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  system("cd $sites_apache");
  system("sudo a2ensite $nom_dom");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Puedes simplificarlo a
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  system("cd $sites_apache ;sudo a2ensite $nom_dom");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

pero da el caso que a a2ensite le da igual dónde estés ejecutándolo, así que al final queda
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  system("sudo a2ensite $nom_dom");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Ahora bien... ¿qué es lo que hace a2ensite? Pues, aparte de unos controles, solo esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
ln -sf $SYSCONFDIR/sites-available/$SITENAME $SYSCONFDIR/sites-enabled/$SITENAME
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
es decir, un enlace simbólico entre el directorio de sites-available y sites-enabled. Finalmente, pide al usuario que haga un reload del Apache. O sea, que lo puedes hacer todo desde Perl: el enlace simbólico lo puedes hacer con la función symlink(). Y el reload, con un system().

Recuerda: si estás llamando a perl dentro de perl, es que estás haciendo algo mal.

Y cualquier llamada con system(), es costosa.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Script para crear subdominios automaticamente

Notapor cmp » 2009-07-24 07:45 @364

Muchísimas gracias por todos los consejos y correcciones.
Recuerda: si estás llamando a perl dentro de perl, es que estás haciendo algo mal.

¡Esto me lo apunto!
El código ha quedado mucho más elegante y eficiente, la verdad:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use File::Copy;
  4. use Text::Template;
  5. use Tie::File;
  6.  
  7. #perl genera_dominio.pl  NOMBRE_SUBDOMINIO  E-MAIL
  8.  
  9. my $nom_dom = $ARGV[0]; #p.e. nombre que el usuario quiere para subdominio
  10. my $sites_apache = "/etc/apache2/sites-available";
  11. my $SYSCONFDIR = "/etc/apache2/";
  12. my $ruta = "$sites_apache/$nom_dom";
  13. my $mail = $ARGV[1]; #recogemos el e-mail del usuario
  14. my $dominio = "www.$nom_dom.dominio.com";
  15. my $ubicacion = "/var/www/$nom_dom";
  16. my $log_error = "/var/log/apache2/error_$nom_dom.log";
  17. my $log_custom = "/var/log/apache2/access_$nom_dom.log";
  18.  
  19. #Comprobamos que no exista ya
  20. if (-e "$sites_apache/$nom_dom") {
  21.     print "El nombre de subdominio $nom_dom ja existe ! \n";
  22. }
  23. else {
  24.  
  25.   #Tenemos una plantilla con los valores clave a cambiar  
  26.   my $template = Text::Template->new(TYPE => 'FILE', SOURCE => "$sites_apache/plantilla")
  27.              or die "Couldn't construct template: $Text::Template::ERROR";
  28.  
  29.   my %vars = (EMAIL => $mail,
  30.               DOMINIO => $dominio,
  31.               UBICACION => $ubicacion,
  32.               LOG_ERROR => $log_error,
  33.               LOG_CUSTOM => $log_custom,
  34.              );
  35.  
  36.   my $result = $template->fill_in(HASH => \%vars);
  37.  
  38.   #Creamos el nuevo fichero de config.
  39.   open CONFIG, ">$sites_apache/$nom_dom";
  40.  
  41.   if (defined $result) { print CONFIG $result }
  42.   else { die "Couldn't fill in template: $Text::Template::ERROR" }
  43.   close(CONFIG);
  44.  
  45.   #Añadimos el subdominio en /etc/hosts para simular DNS a nivel local
  46.   tie my @array, 'Tie::File', "/etc/hosts" or die "Error Tie::File";
  47.   for (@array) { s/#AFEGIR_DOM_AQUI/$domini #AFEGIR_DOM_AQUI/g; }
  48.  
  49.   #Activamos el nuevo Vhost
  50.   my $ret = symlink("$SYSCONFDIR/sites-available/$nom_dom","$SYSCONFDIR/sites-enabled/$nom_dom");
  51.   if (!$ret){ print "Error al crear symbolic link \n"; }
  52.  
  53.   #Creamos el directorio para el nuevo site
  54.   mkdir "/var/www/$nom_dom", 0755 or warn"No se pudo crear el directorio: $!";
  55.   #Creamos un index.html para que se muestre algo hasta que el usuario ponga su contenido
  56.   open(fd,">/var/www/$nom_dom/index.html") or die "No se pudo crear el fichero index.html\n";  
  57.   print fd "<title>$dominio</title> <html>Espacio web $nom_dom</html>";
  58.   close(fd);
  59.  
  60.   #Reiniciamos apache para que los cambios tengan efecto
  61.   system("sudo /etc/init.d/apache2 reload");
  62.  
  63.   #Para las pruebas
  64.   print "\n-------------------\nSe creó el dominio $dominio con éxito! \n";
  65.   print "Correo electronico: $mail \n";
  66.   print "El log de errores : $log_error \n";
  67.   print "El log de accesos : $log_custom \n-------------------\n";
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Ahora tan solo hay una llamada a system() para reiniciar Apache.
Para añadir el nuevo dominio al fichero hosts he utilizado la misma técnica de antes de la sustitución pero utilizando el use Tie::File que me comentaste. Es la mejor forma que se me ha ocurrido (no he encontrado muchos ejemplo que es como mejor entiendo estas cosas). Otra forma seria añadir siempre al final algo como:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. 127.0.0.1 Nuevodominio.com 

Pero de esta forma se repetiría muchas veces '127.0.0.1' innecesariamente.

De nuevo gracias, es de gran ayuda que alguien con experiencia en esto te eche una mano, ya que para un proyecto de la universidad estoy tocando demasiados lenguajes y es imposible empaparse de todos a un nivel profundo (ya me gustaría).

Y una última cosita. Tengo un servidor de XML-RPC también en Perl y utilizo Frontier::Daemon. ¿Crees que es la mejor opción?
Si me surge alguna otra duda ya me verás por aquí dando la lata. :)

Un saludo.
cmp
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2007-05-28 10:43 @488

Re: Script para crear subdominios automaticamente

Notapor explorer » 2009-07-24 10:08 @464

No conozco Frontier::Daemon, no puedo decirte qué tal es.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Script para crear subdominios automaticamente

Notapor cmp » 2009-07-28 12:20 @555

Ok, gracias.

Ahora tengo un problema para borrar un directorio (que puede contener subdirectorios). Para evitar utilizar una llamada al sistema he encontrado File::Path que puede hacerlo.

Resumiendo. Tengo el siguiente código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use File::Path 'remove_tree';
  4.  
  5. remove_tree( 'var/www/borrar/',  {error => \my $err} );
  6.   if (@$err) {
  7.       for my $diag (@$err) {
  8.           my ($file, $message) = %$diag;
  9.           if ($file eq '') {
  10.               print "general error: $message\n";
  11.           }
  12.           else {
  13.               print "problem unlinking $file: $message\n";
  14.           }
  15.       }
  16.   }
  17.   else {
  18.       print "No error encountered\n";
  19.   }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Pues me dice que no ha habido errores pero no me elimina el directorio... ¿Alguna idea?

Un saludo
Última edición por explorer el 2009-07-28 13:51 @619, editado 1 vez en total
Razón: Ortografía
cmp
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2007-05-28 10:43 @488

Re: Script para crear subdominios automaticamente

Notapor explorer » 2009-07-28 13:50 @618

Te falta un '/' delante de 'var'.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Script para crear subdominios automaticamente

Notapor cmp » 2009-07-29 10:53 @495

Madre mía :oops:
Vaya días que llevo...
Lo que es raro, es que no lo reportara como error.

Muchas gracias.
cmp
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2007-05-28 10:43 @488

Re: Script para crear subdominios automaticamente

Notapor explorer » 2009-07-29 11:41 @529

He estado mirando el código del módulo: no reporta error porque no ha encontrado ningún fichero qué borrar.

Una forma de saber si lo ha hecho bien es guardar el valor que devuelve la función: es el número de ficheros que ha conseguido borrar. En tu caso, te devuelve un 0.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Script para crear subdominios automaticamente

Notapor cmp » 2009-07-30 11:06 @504

Cierto, muchas gracias ya funciona perfecto.
cmp
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2007-05-28 10:43 @488


Volver a Avanzado

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados

cron