Tag Archive: Logs


Que titulo Tete! Bueno, mas allá de lo largo del titulo de este post, hoy me encontraba un poco con ganas de repasar programacion en Shell Scripts de bash asi que tome un viejo script  que encontré en internet hace un tiempo. En aquel momento  lo habia modificado un poco para que anduviese asi que me decidi mejorarlo mas aun porque la verdad cada vez que añadia una nueva maquina virtual tenia que cambiar muchisimas lineas de código.

La gente de VirtualBox provee en sus paquete una herramienta llamada VBoxManage que es para aquellos que empleamos  virtualbox como gestor de maquinas virtuales y necesitamos ejecutarlas  en un servidor sin necesidad de hacer uso del modo gráfico e interactivo donde tenemos que arrancar los host virtualizados a mano.  Este ejecutable nos permite gestionar completamente la administracion de host virtualizados desde linea de comandos con la posibilidad de ejecutarlas de fondo sin activacion del entorno grafico al que todos estamos acostumbrados.

El script gestiona VBoxManage para permitir iniciar/detener/ver el estado de cuantas  maquinas virtuales tengamos, lo anexan al directorio  /etc/init.d/ y como enlace al /etc/rcX.d de su preferencia, en mi caso que uso debian en el /etc/rc2.d/  y  ya podemos empezar a usarlo luego de adecuarlo a nuestras necesidades solo modificando unas pocas variables con nuestro editor de textos favorito.  En las variables a modificar especificaremos datos como nombre de las maquinas virtuales, usuario con el que se ejecuta Virtualbox, tiempo máximo de espera para el apagado de una maquina virtual.

A continuación mi script, tada!!!

#!/bin/bash

##
## virtualbox-daemon-mcy.sh
##
## Version : 0.2 27.01.2012 03:05:43
##
## Descripcion: Demonio de inicio de Maquinas virtuales de VirtualBox
## El objetivo es automatizar el inicio de maquinas virtuales de
## Virtualbox en modo headless ( que es cuando nose ejecutan en modo
## interactivo, sin interfaz grafica, sino en background ). Se soportan
## el inicio de clientes windows como Linux y se mantiene un log por
## fechas de cuando se arranco/detuvo/guardo una sesion. Los logs se
## almacenan en el $HOME/.VBoxLogs del usuario que tiene las VM.
##
## Copyright 2012 Cesar Yanez <emanceyan@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
## MA 02110-1301, USA.
### MODIFICABLE POR USUARIO ### MODIFICABLE POR USUARIO #######
##
## Info: VMs Windows ###
##
## Ayuda:
## VBX_WIN_TOTAL : cantidad de Maquinas Virtuales con Win
##
## VBX_WIN_NAMEX : nombre de la maquina virtual X con Win
## VBX_WIN_USERX : usuario admin de la maquina virtual X
## VBX_WIN_PASSX : password admin de la maquina virtual X
## VBX_WIN_NUMIPX : numero ip de la maquina virtual X
##
## Si hay mas de 4 maquinas virtuales con windows copiar
## y repetir secciones sin repetir numeros
##
VBX_WIN_TOTAL=1

VBX_WIN_NAME1="Windows XP"
VBX_WIN_USER1="cesar"
VBX_WIN_PASS1="cesar"
VBX_WIN_NUMIP1="192.168.1.140"

VBX_WIN_NAME2=""
VBX_WIN_USER2=""
VBX_WIN_PASS2=""
VBX_WIN_NUMIP2=""

VBX_WIN_NAME3=""
VBX_WIN_USER3=""
VBX_WIN_PASS3=""
VBX_WIN_NUMIP3=""

## Info: VMs Linux ###
##
## Ayuda:
## VBX_LIN_TOTAL : cantidad de Maquinas Virtuales con Linux
##
## VBX_LIN_NAMEX : nombre de la maquina virtual X con Linux
##
VBX_LIN_TOTAL=1

VBX_LIN_NAME1="DebianSqueeze"
VBX_LIN_NAME2=""
VBX_LIN_NAME3=""
VBX_LIN_NAME3=""

### Info: Usuario que es propietario de las maquinas virtuales
###
VBX_USR="rondamon"
### Maxima cantidad de tiempo a esperar para que se apague una
### sesion
MAX_SEC=30

### MODIFICABLE POR USUARIO ### MODIFICABLE POR USUARIO #######

###### NO MODIFICAR ###### NO MODIFICAR ###### NO MODIFICAR ####

setEnvVar(){
 RPC_NET=`which net`
 SYS_SU=`which su`
 SYS_AWK=`which awk`
 SYS_GREP=`which grep`
 SYS_TR=`which tr`
 SYS_WC=`which wc`
 SYS_CUT=`which cut`
 SYS_MKD=`which mkdir`
 SYS_CHW=`which chown`
 CUR_USR=`whoami`
 VBX_MNG=`which VBoxManage`
 VBX_USR_HOME=`$SYS_GREP $VBX_USR /etc/passwd|$SYS_CUT -d: -f6`
 VBX_DIR_LOGS=$VBX_USR_HOME/.VBoxLogs
 VBX_LOG_START=$VBX_DIR_LOGS/start.`date '+%d%m%y'`.logs
 VBX_LOG_STOP=$VBX_DIR_LOGS/stop.`date '+%d%m%y'`.logs
 VBX_LOG_SAVE=$VBX_DIR_LOGS/save.`date '+%d%m%y'`.logs
 if [ ! -d $VBX_DIR_LOGS ]; then
 $SYS_MKD $VBX_DIR_LOGS
 fi
 $SYS_CHW $VBX_USR:$VBX_USR $VBX_DIR_LOGS
}

checkVmRunning(){
 VM_TOTAL=`expr $VBX_WIN_TOTAL + $VBX_LIN_TOTAL`
 VM_TOTAL_RUNNING=`$SYS_SU $VBX_USR -c "$VBX_MNG list runningvms |$SYS_WC -l"`
 if [ $VM_TOTAL_RUNNING -eq $VM_TOTAL ]; then
 echo " - Todas las VMs estan ejecutandose"
 return 10
 elif [ $VM_TOTAL_RUNNING -eq 0 ]; then
 echo " - Ninguna VMs en ejecucion"
 return 0
 elif [ $VM_TOTAL_RUNNING -ne $VM_TOTAL ]; then
 echo " - Algunas VMs estan ejecutandose"
 return 5
 fi
}

checkStatusVms(){
 if [ "$1" = " " ]; then
 return 10
 elif [ "$1" != " " ]; then
 ## VM_STATUS=`$SYS_SU -c "$VBX_MNG showvminfo $1 |$SYS_GREP ^State |$SYS_AWK '{print $2}'" $VBX_USR`
 VM_STATUS=`$SYS_SU $VBX_USR -c "$VBX_MNG showvminfo \"$1\" |$SYS_GREP ^State |$SYS_TR -s ' ' ' '|$SYS_CUT -d ' ' -f 2"`
 ### echo VMSTATUSSSSSS $VM_STATUS
 if [ "$VM_STATUS" = "saved" ]; then return 1
 elif [ "$VM_STATUS" = "powered" ]; then return 2
 elif [ "$VM_STATUS" = "running" ]; then return 3
 fi
 fi
}

startWindows(){
 for i in `seq 1 $VBX_WIN_TOTAL`; do
 NAMEL="VBX_WIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 1 ] || [ $STS -eq 2 ]; then
 echo " - Iniciando VM Windows: " `eval $NAMELL`
 $SYS_SU $VBX_USR -c "$VBX_MNG startvm \"`eval $NAMELL`\" -type headless >> ${VBX_LOG_START} 2>&1"
 elif [ $STS -eq 3 ]; then
 echo " - La VM `eval $NAMELL` ya esta ejecutandose"
 fi
 done
}

stopWindows(){
 for i in `seq 1 $VBX_WIN_TOTAL`; do
 NAMEL="VBX_WIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 NAMEU="VBX_WIN_USER$i"; NAMEUU='eval "echo \$$NAMEU"'
 NAMEP="VBX_WIN_PASS$i"; NAMEPP='eval "echo \$$NAMEP"'
 NAMEI="VBX_WIN_NUMIP$i"; NAMEII='eval "echo \$$NAMEI"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 2 ]; then
 echo " - "`eval $NAMELL`" esta apagada"; return 0
 elif [ $STS -eq 1 ]; then
 echo " - "`eval $NAMELL`" esta guardada"; return 0
 elif [ $STS -eq 3 ]; then
 echo -n " - "`eval $NAMELL`" deteniendo ..."
 ## $RPC_NET rpc SHUTDOWN -t 0 -C "Apagado desde el servidor de maquinas vituales" -f -I \"`eval $NAMEII`\" -U `eval $NAMEUU`%`eval $NAMEPP`
 $SYS_SU $VBX_USR -c "$VBX_MNG controlvm \"`eval $NAMELL`\" acpipowerbutton >> ${VBX_LOG_STOP} 2>&1"
 for j in `seq 1 $MAX_SEC`; do
 sleep 1; echo -n "$j."
 done
 echo ''; return 1
 fi
 done
}

saveWindows(){
 for i in `seq 1 $VBX_WIN_TOTAL`; do
 NAMEL="VBX_WIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 2 ] || [ $STS -eq 1 ]; then echo ''
 elif [ $STS -eq 3]; then
 echo " - Salvando VM Windows: " `eval $NAMELL`
 $SYS_SU $VBX_USR -c "$VBX_MNG controlvm \"`eval $NAMELL`\" savestate >> ${VBX_LOG_SAVE} 2>&1"
 fi
 done
}

startLinux(){
 for i in `seq 1 $VBX_LIN_TOTAL`; do
 NAMEL="VBX_LIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 1 ] || [ $STS -eq 2 ]; then
 echo " - Iniciando VM Linux: " `eval $NAMELL`
 $SYS_SU $VBX_USR -c "$VBX_MNG startvm \"`eval $NAMELL`\" -type headless >> ${VBX_LOG_START} 2>&1"
 elif [ $STS -eq 3 ]; then
 echo " - La VM Linux `eval $NAMELL` ya esta ejecutandose"
 fi
 done
}

stopLinux(){
 for i in `seq 1 $VBX_LIN_TOTAL`; do
 NAMEL="VBX_LIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 2 ]; then
 echo " - "`eval $NAMELL`" esta apagada"
 return 0
 elif [ $STS -eq 1 ]; then
 echo " - "`eval $NAMELL`" esta guardada"
 return 0
 elif [ $STS -eq 3 ]; then
 echo -n " - "`eval $NAMELL`" deteniendo ..."
 $SYS_SU $VBX_USR -c "$VBX_MNG controlvm \"`eval $NAMELL`\" acpipowerbutton >> ${VBX_LOG_STOP} 2>&1"
 for j in `seq 1 $MAX_SEC`; do
 sleep 1; echo -n "$j."
 done
 echo ''; return 1
 fi
 done
}

saveLinux(){
 for i in `seq 1 $VBX_LIN_TOTAL`; do
 NAMEL="VBX_LIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 2 ] || [ $STS -eq 1 ]; then echo ''
 elif [ $STS -eq 3]; then
 echo " - Guardando VM Linux: " `eval $NAMELL`
 $SYS_SU $VBX_USR -c "$VBX_MNG controlvm "`eval $NAMELL`" savestate >> ${VBX_LOG_SAVE} 2>&1"
 fi
 done
}

statusVm(){
 for i in `seq 1 $VBX_WIN_TOTAL`; do
 NAMEL="VBX_WIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 1 ]; then
 echo " - STATUS: "`eval $NAMELL`" esta guardada"
 elif [ $STS -eq 2 ]; then
 echo " - STATUS: "`eval $NAMELL`" esta apagada"
 elif [ $STS -eq 3 ]; then
 echo " - STATUS: "`eval $NAMELL`" esta ejecutandose"
 fi
 done
 for i in `seq 1 $VBX_LIN_TOTAL`; do
 NAMEL="VBX_LIN_NAME$i"; NAMELL='eval "echo \$$NAMEL"'
 checkStatusVms "`eval $NAMELL`"
 STS=$?
 if [ $STS -eq 1 ]; then
 echo " - STATUS: "`eval $NAMELL`" esta guardada"
 elif [ $STS -eq 2 ]; then
 echo " - STATUS: "`eval $NAMELL`" esta apagada"
 elif [ $STS -eq 3 ]; then
 echo " - STATUS: "`eval $NAMELL`" esta ejecutandose"
 fi
 done
 echo ''
}

setEnvVar
echo ''
echo '#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*'
echo '* Script de Arranque y Apagado de Maquinas Virtuales (VMs) #'
echo '#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*'
echo ''
case $1 in
 start)
 echo '*** Iniciando VMs, espere a que inicien los sistemas ***'
 startLinux
 startWindows
 ;;
 stop)
 echo '*** Deteniendo VMs, espere a que terminen de apagar los sistemas ***'
 stopLinux
 stopWindows
 ## si no se apago la VM se guarda su estado para proteccion del filesystem
 checkVmRunning
 STS=$?
 if [ $STS -ne 0 ]; then
 saveWindows
 saveLinux
 elif [ $STS -eq 0 ]; then echo ''; echo " - Todas las VMs Apagadas"; echo ''
 fi
 ;;
 status)
 statusVm
 ;;
 restart)
 $0 stop; $0 start
 ;;
 *)
 echo ''; echo "Modo de Uso: $0 {start|stop|status|restart}"; echo ''
 ;;
esac

###### NO MODIFICAR ###### NO MODIFICAR ###### NO MODIFICAR ####

Algunas cosas a mejorar a futuro son el tema del apagado con sistemas Windows, ya que lo hice por llamada rpc del ejecutable net del paquete de samba, pero no pude conseguir que funcione en todos los sistemas windows donde he probado, de todas formas  si quieren probarlo deben descomentar la linea numero 171 dentro de la función stopWindows y comentar la linea 172. De otra forma asi tal como esta por defecto en el caso de host Windows procederá a un apagado normal como si hubieramos pulsado el boton de apagado comun y corriente.

Casi me olvido, esa pequeñes de script va con licencia GPL asi que sientanse libres de modificarlo como quieran y adaptarlo a sus necesidades.

Dejo link de descarga mediafire: http://www.mediafire.com/?4b8s692dhlgqc7p

Saludos a todos

Este post surge particularmente por un problema que tuve recientemente en una Lan donde el unico acceso a internet esta reglado por un Firewall GNU/Linux que a su vez  tiene un servidor web Apache2 corriendo algunos aplicativos internos hacia la Lan, donde, por su lado,  muchas estaciones de trabajo de usuarios cuentan con un sistema operativo MS Windows con instalaciones del Antivirus Eset Nod 32.

El problema, según lo que he podido observar,  radica en que algunas estaciones con dicho antivirus, al no poder acceder a internet , debido probablemente a  alguna politica de firewall ,  suelen tratar de (al parecer) obtener sus updates del servidor con apache2. Digo esto debido a la inmensa cantidad de lineas de Logs que se generan en los archivos de logs access.log y error.log, ubicados en las siguientes rutas:

/var/log/apache2/access.log

/var/log/apache2/error.log

Tal es la cantidad de lineas generadas que los archivos han llegado a crecer en un  promedio aproximado de 1 giga por hora en el caso de access.log y un poco menos en error.log, calculo que la varianza en el crecimiento de este archivo dependerá de la cantidad de terminales con dicho antivirus que colapsen con alguna regla firewall que evite su acceso hacia el server contra el que se actualicen.

En access.log la linea que genera el crecimiento desmesurado del archivo es como la siguiente, lo que al parecer es un intento de actualización vía protocolo http.

10.20.30.5 – – [01/Jun/2010:12:06:39 -0300] “GET http://um10.eset.com/eset_upd/update.ver HTTP/1.1” 404 391 “-” “ESS Update (Windows; U; 32bit; VDB 6651; BPC 3.0.621.0; OS: 5.1.2600 SP 3.0 NT; CH 1.1; LNG 1033; x32c; UPD AUTOSELECT; APP eav”
10.20.30.6 – – [01/Jun/2010:12:09:20 -0300] “GET http://um10.eset.com/eset_eval/update.ver HTTP/1.1” 404 392 “-” “ESS Update (Windows; U; 32bit; VDB 7210; BPC 3.
0.621.0; OS: 5.1.2600 SP 3.0 NT; CH 1.1; LNG 1033; x32c; UPD AUTOSELECT; APP eav”
En el error.log observe una reiteracion de esta linea:
[Thu Jun 01 13:06:39 2010] [error] [client 10.20.30.5] File does not exist: /var/www/eset_upd
Lo cual parece una respuesta correcta por parte de Apache2 al no encontrar la ruta que solicita Eset en el servidor.
Si bien en algún momento pensé en que una de las soluciones posibles seria reducir el lapso de rotado de los archivos de logs, esto, de acuerdo al grado de crecimiento observado tanto en access.log como en error.log, implicaría un rotado por hora para evitar el crecimiento alocado en el tamaño de los archivos a fin de evitar que llenen la partición /var  y también para agilizar su lectura.
Escogiendo que loguear en Apache 2
Para este caso preferi husmear un poco mas en la documentación de Apache2 y me di con el parámetro de configuración SetEnvIf, que me permite definir variables de ambiente basadas en patrones de matching en una solicitud web, dicho patrón puede estar dado por una expresión regular que identifique una porcion de una URL, un tipo de petición o vía algún  otro campo de busqueda,  para luego asignárselo a una variable. Durante la definición del archivo de access.log  se debe referenciar dicha variable con un negador para que dichos patrones sean excluidos del proceso de logging de acceso.
Tal es asi que en mi caso modifique /etc/apache2/sites-enabled/sistema-interno, que es el archivo base de definicion de los sistemas web internos. y añadi entre los tags de virtualhost, las siguientes lineas:
SetEnvIf Request_URI “eset_upd” nologuear
SetEnvIf Request_URI “eset_eval” nologuear
Estas lineas estan antes de las definiciones de los archivos de logs de acceso y de errores, que normalmente vienen por defecto con los siguientes valores:
CustomLog /var/log/apache2/access.log combined
ErrorLog /var/log/apache2/error.log
En las definiciones de SetEnvIf se analizan las URL(URI) que contengan las cadenas “eset_upd” y “eset_eval” y se asignan a la variable nologuear.
Luego. modificamos la definicion del archivo de logs de accesos, el cual normalmente es una linea similar a esta:
CustomLog /var/log/apache2/access.log combined
y la dejamos como la siguiente:
CustomLog /var/log/apache2/access.log combined  env=!nologuear
Esta es la linea magica que nos permite excluir de nuestro archivo de logs de accesos cualquier patron concordante con las cadenas que especificamos mediante SetEnvIf  en la variable nologuear.
Ahora si estas pensando que con esto se termino todo, aun me faltaba evitar que siguiese creciendo el archivo error.log.
Aunque con los parametros anteriores evitamos que el logging de acceso de Eset quede registrado, eso no implica que apache2 deje de  registar en el archivo error.log los mensajes de la ruta no encontrada.
Para esto me simplifique un poco la vida y modifique la el nivel de debug del ErrorLog , con el parametro LogLevel.
Modifique el parámetro LogLevel que venia por default al parecer cambiándolo del siguiente valor:
LogLevel warn
a la siguiente linea
LogLevel crit
No creo que sea la solucion mas adecuada, pero si fue la que funciono:). Créanme cuando digo que pense que me iba a dar con la misma versatilidad del parámetro CustomLog respecto a la definición de  parámetros a excluir del Log, pero no fue posible, no lo encontré en la documentación de Apache2.
Finalmente para que los cambios efectuados surgan efecto debemos reiniciar el servicios Apache2:
En Debian o derivados:
# /etc/init.d/apache2 restart