Páginas

jueves, 9 de mayo de 2013

Creating new standalone instance to jboss

Siguiendo con las recomendaciones de buenas practicas de Red Hat en el curso de JBoss (JBoss Application Administration I) de no montar las aplicaciones en la instancias por defecto "standalone", lo ideal es hacer una copia de "standalone" con otro nombre y subir esta.

Basándome en esto instale JBoss desde Red Hat Network y procedí a crear una copia de "standalone" e intente subirla; Me encontré que para hacer esto con la instalación desde Red Hat debemos modificar muchos archivos y directorios, así que aquí es donde entra bash script.

Cree este script con el fin de hacer esta tarea lo más automática posible, ahora ya podremos disfrutar de nuestro servidor JBoss en modo standalone pero con otro nombre.




#!/bin/sh
#
#  jboss_new_instance
#
#  Copyright (C) 2013 - Luis Fernando Maldonado Arango
#  Copyright (C) 2013 - Summan S.A.S.
#
#  jboss_new_instance 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 3 of the License, or
#  (at your option) any later version.
#
#  jboss_new_instance 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 checkWand.  If not, see <http://www.gnu.org/licenses/>.
#

# Source function library.
. /etc/init.d/functions

WHITE=$(tput bold ; tput setaf 7)
RED=$(tput bold ; tput setaf 1)
GREEN=$(tput bold ; tput setaf 2)
NORMAL=$(tput sgr0)

echoWhite() {
   echo -en "$WHITE$1$NORMAL"
}

echoRed() {
   echo -e "$RED$1$NORMAL"
}

BASE_NAME=`basename $0`
E_NOROOT=1

if [ "$(id -u)" != "0" ]; then
   echoRed "$BASE_NAME: This script must be run as root." 1>&2
   exit $E_NOROOT
fi

JBOSS_PATH=/etc/jbossas
JBOSS_CONF=/etc/sysconfig/jbossas
JBOSS_LOG=/var/log/jbossas
JBOSS_LIB=/var/lib/jbossas
JBOSS_HOME=/usr/share/jbossas
JBOSS_BIN=$JBOSS_HOME/bin
JBOSS_SCRIPT=/etc/init.d



askNonBlank() {
  while [ 1 ]; do
    echoWhite "name of the new instance? [] "
    read response
        if [ ! -z $response ]; then
          break
        fi
        echoRed "A non-blank answer is required"
  done
}

# copy standalone to new-intance
copyInstance() {
   cp -a $JBOSS_PATH/standalone $JBOSS_PATH/$response 2>&1
}

# modify config file jbossas (/etc/sysconfig/jbossas)
modifyConfig() {
    sed -i 's/# JBOSSCONF=.*/JBOSSCONF="'$response'"/g ; s/JBOSSCONF=.*/JBOSSCONF="'$response'"/g' $JBOSS_CONF 2>&1
}

# copy dir log jboss
copyDir() {
    cp -a $JBOSS_LOG/standalone $JBOSS_LOG/$response 2>&1
}

# copy lib jboss
copyLib() {
    cp -a $JBOSS_LIB/standalone $JBOSS_LIB/$response 2>&1
}

# create simbolic-link $response
createSlink() {
CSL=0

    if [ $CSL -eq 0 ]; then
    ln -s $JBOSS_LIB/$response $JBOSS_HOME/$response 2>&1
        if [ $? -ne 0 ]; then
        CSL=1
        fi
    fi
    if [ $CSL -eq 0 ]; then
    rm -f $JBOSS_HOME/$response/configuration 2>&1
        if [ $? -ne 0 ]; then
        CSL=1
        fi
    fi
    if [ $CSL -eq 0 ]; then
    ln -s $JBOSS_PATH/$response $JBOSS_HOME/$response/configuration 2>&1
        if [ $? -ne 0 ]; then
        CSL=1
        fi
    fi
    if [ $CSL -eq 0 ]; then
    rm -f $JBOSS_HOME/$response/log 2>&1
        if [ $? -ne 0 ]; then
        CSL=1
        fi
    fi
    if [ $CSL -eq 0 ]; then
    ln -s $JBOSS_LOG/$response $JBOSS_HOME/$response/log 2>&1
        if [ $? -ne 0 ]; then
        CSL=1
        fi
    fi
    if [ $CSL -eq 0 ]; then
    chown -R jboss.jboss $JBOSS_HOME/$response/ 2>&1
        if [ $? -ne 0 ]; then
        CSL=1
        fi
    fi
}

# copy script start jboss and config file
copyScript() {
    cp -a $JBOSS_BIN/standalone.sh $JBOSS_BIN/$response.sh 2>&1
    if [ $? -eq 0 ]; then
        cp -a $JBOSS_BIN/standalone.conf $JBOSS_BIN/$response.conf 2>&1
    fi  
}

# change value script start jboss
changeScriptStart() {
    sed -i 's/standalone.conf/'$response'.conf/g' $JBOSS_BIN/$response.sh 2>&1
    if [ $? -eq 0 ]; then
        sed -i 's/JBOSS_HOME\/standalone/JBOSS_HOME\/'$response'/g' $JBOSS_BIN/$response.sh 2>&1
    fi
}

# copy script create management user
copySSJboss() {
    cp -a $JBOSS_BIN/add-user.sh $JBOSS_BIN/add-user-$response.sh 2>&1
}
# change value script start jboss
changeValueScript() {
    sed -i 's/#JAVA_OPTS="\$JAVA_OPTS -Djboss\.server\.config\.user\.dir=\.\.\/standalone\/configuration -Djboss\.domain\.config\.user\.dir=\.\.\/domain\/configuration"/JAVA_OPTS="\$JAVA_OPTS -Djboss\.server\.config\.user\.dir=\/usr\/share\/jbossas\/'$response'\/configuration"/g' $JBOSS_BIN/add-user-$response.sh 2>&1
}
# create management user jboss
createMUJboss() {
    $JBOSS_BIN/add-user-$response.sh 2>&1
}

rc=$?
askNonBlank
if [ -n $response ]; then
    service jbossas stop
    action $"Copy standalone to new-intance: " copyInstance
    if [ $? -ne 0 ]; then
        exit $rc    
    fi
    action $"Modify config file jbossas: " modifyConfig
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Copy dir log jboss: " copyDir
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Copy lib jboss: " copyLib
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Create simbolic-link: " createSlink
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Copy script start jboss and config file: " copyScript
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Change value script start jboss: " changeScriptStart
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Copy script create management user: " copySSJboss
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Change value script start jboss: " changeValueScript
    if [ $? -ne 0 ]; then
        exit $rc
    fi
    action $"Management user jboss: " createMUJboss
    service jbossas restart
fi

Código fuente: create-instance-JB.sh

Espero alguien lo pruebe y le sea útil, y por supuesto me haga las sugerencias pertinentes.

domingo, 5 de mayo de 2013

bulk processing to create LVM

Hola, resulta que alguien me pidio que creara nada más y nada menos que 200 lvm, se imaginan hacer esto uno a uno...!!!, se me ocurrio hacer un script que se alimentara de un insumo (archivo separado por comas) donde se definiera por linea el lvm a crear.

el insumo luce así: "vg-name, lvm-name, lv-size"

Ejm.

vg0, lv-opt, 30G
vg0, lv-var, 20G
vg1, lv-home, 50G
vg1, lv-usr, 20G

Así que los VG ya estaban creados solo debía de proceder a crear los LVM.

createLVM.sh


#!/bin/sh
#
#  createLVM.sh
#
#  Copyright (C) 2012 - Luis Fernando Maldonado Arango
#
#  createLVM.sh 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 3 of the License, or
#  (at your option) any later version.
#
#  createLVM.sh 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 checkWand.  If not, see <http://www.gnu.org/licenses/>.
#
BOLD_RED_TEXT='\033[1;31m'
BOLD_GREEN_TEXT='\033[1;32m'
BOLD_PURPLE_TEXT='\033[1;35m'
RESET_TEXT='\033[0m'
function echoRed() {
    echo -e "$BOLD_RED_TEXT$1$RESET_TEXT"
}

function echoGreen() {
    echo -e "$BOLD_GREEN_TEXT$1$RESET_TEXT"
}

function echoPurple() {
    echo -e "$BOLD_PURPLE_TEXT$1$RESET_TEXT"
}
# Function to create the  logical volume in LVM
function createLV() {
    echoGreen "Creando Logical Volumes '$1' segun archivo insumo"
    lvcreate -n $1 -L $2G $3
    echoGreen "la siguiente linea confirma que el Logical Volumes fue creado:"
    lvs | grep $1
}

function formatLV() {
    echoGreen "Formateando Logical Volumes '$1'."
    if [[ -e /dev/$3/$1 ]]; then
        mke2fs -t ext3 /dev/$3/$1
        tune2fs -c 0 -i 0 /dev/$3/$1
    else
        echoRed "Logical Volumes $1 no existe!"
        exit
    fi

}

function createMountPoint() {
    echoGreen "Creando punto de montage '/$1' para el Logical Volumes '$1'."
    if [[ ! -d /$1 ]]; then
    mkdir /$1
    else
        echoRed "Punto de montage '/$1' ya existe"
    fi
}

function createFStab() {
    echoGreen "Creando linea en fstab temporal para el filesystem '/$1'."
    if [[ ! `grep /dev/mapper/$3-$1 fstab.tmp` ]]; then
        echo "/dev/mapper/$3-$1 /$1 ext3    defaults    0 0" >> fstab.tmp
        echo "==========================================================="
    fi
}
while read LINE
do
  VGNAME=`echo $LINE | cut -d, -f1`
  LVMNAME=`echo $LINE | cut -d, -f2`
  SIZELV=`echo $LINE | cut -d, -f3`

  createLV $LVMNAME $SIZELV $VGNAME
  formatLV $LVMNAME $SIZELV $VGNAME
  createMountPoint $LVMNAME $SIZELV $VGNAME
  createFStab $LVMNAME $SIZELV $VGNAME
done < "$1"
Ahora bien solo debo ejecutar el script entregando mi archivo de insumo... y magia, adicional se crea un archivo temporal de fstab para que luego lo inserten en el original y todos tus nuevos fs se monten automáticamente en cada inicio.

$ ./createLVM.sh insumo.txt

Filtrado de IPs "unknown" para Zimbra


Para iniciar la creación de un script lo que primero debemos tener es una necesidad, pues este era mi caso, yo necesitaba mejorar el filtrado de spam en el servidor de correo de la compañía... "El filtrado que trae Zimbra CS es bastante bueno, pero yo quería hacer lo mucho mejor".

Realmente lo que quería hacer era bloquear todo origen de correo que no se pudiera resolver correctamente por medio de los PTR, cuando un MTA no logra hacer una buena resolución inversa del origen de correo lo marca como "unknown", suponemos entonces que NO es un origen confiable de correo ó que el servicio de correo no esta bien configurado.

Como este no es un blog para hablar de Zimbra, postfix, ni correo en general, no entrare en detalles de la configuración, solo voy a mostrar como por medio de bashscript cree no solo la lista de IPs a bloquear, si no que también como cree otro script para limpiar los falsos positivos.

Nota: El script "spammers.sh" como yo lo llamo, esta basado en una solución propuesta por Riaan Pretorius colaborador de zimbra.com, yo solo lo adapte a mi necesidad.

Primer Script: spammers.sh


export LANG=C # Adds execution speed

LOG="/var/log/maillog"
TMP_SPAMMERS="/opt/zimbra/conf/postfix_rbl_ip_spammers.tmp"
TMP_LOG1="/opt/zimbra/conf/postfix_rbl_ip_spammers.log1"
TMP_LOG2="/opt/zimbra/conf/postfix_rbl_ip_spammers.log2"
SPAMMERS="/opt/zimbra/conf/postfix_rbl_ip_spammers"
WHITELIST="/opt/zimbra/conf/postfix_rbl_ip_whitelist"

awk '/ connect from/ {print $8}' $LOG | \
grep unknown | \
awk '{print $1}' | \
cut -d[ -f2 | cut -d] -f1 | \

while read ip ; do
    host $ip > /dev/null 2>&1;\
    if [ $? -ne 0 ] ; echo "$ip         REJECT" >> $TMP_SPAMMERS; then
        echo "$ip";
    fi;
done

cat $TMP_SPAMMERS | sort | uniq | grep -v -f $WHITELIST > $TMP_LOG1
cat $TMP_LOG1 $SPAMMERS > $TMP_LOG2
cat $TMP_LOG2 | sort | uniq | grep -v -f $WHITELIST > $SPAMMERS
rm -f $TMP_LOG1 $TMP_LOG2 $TMP_SPAMMERS
su - -c "postmap $SPAMMERS" zimbra
su - -c "zmmtactl restart" zimbra


En este script se hace uso de variables, awk (pattern scanning and processing language), grep (print lines matching a pattern), sort (sort lines of text files), uniq (report or omit repeated lines) y cut (remove sections from each line of files) para obtener la IP a bloquear, todo esto por medio de un bucle con "while". Luego de determinar la IP procedemos a registrarla en los diferentes archivos de configuración.

Este proceso tienen  una falencia y es que muchos servidores de correo no están bien configurados o por lo menos sus registros DNS, así que llegamos al punto de los falsos positivos. Aquí era necesario tener un procedimiento para limpiar de los db de postfix las IPs que eran orígenes correctos y agregarlos a listas blancas, así empece con "whitelist.sh" en colaboración con +Víctor Daniel .

Segundo Script: whitelist.sh


#   Usage: whitelist [options]
#
#  Options:
#    <arg>            DOMINIO ó MAIL
#    --help           This help message

EXPECTED_MIN_ARGS=1
EXPECTED_MAX_ARGS=1
E_BADARGS=65
E_NOROOT=1
BASE_NAME=`basename $0`

if [[ $# -gt $EXPECTED_MAX_ARGS ]] ||
   [[ $# -lt $EXPECTED_MIN_ARGS ]] ||
   [[ $1 == "--help" ]] ; then
  echo "Usage: $BASE_NAME <arg>" 1>&2
  echo "Usage: $BASE_NAME --help" 1>&2
  exit $E_BADARGS
fi

if [ "$(id -u)" != "0" ]; then
   echo "$BASE_NAME: This script must be run as root." 1>&2
   exit $E_NOROOT
fi

LOCK_FILE="/var/lock/whitelist"
ULIMIT_N=`ulimit -n`
let "FLOCK_FD = ULIMIT_N - 1"
START_DATE=`date`
ERROR_EXIT="1"

(
  eval "exec $FLOCK_FD<> $LOCK_FILE"
  if flock -n $FLOCK_FD ; then
# flock START

Slog="/var/log/maillog"
PostPath="/opt/zimbra/conf"
DBSpammers="postfix_rbl_ip_spammers.db"
FSpammers="postfix_rbl_ip_spammers"
FWhitelist="postfix_rbl_ip_whitelist"
IP=`grep $1 $Slog | grep -m 1 -E 'rejected: Access denied' | awk '{print $10}' | cut -d[ -f2 | cut -d] -f1`
 
# 1. buscar bloqueado - recibe parametro "arg" (email ó dominio).
# Ejemplo de log:
# Mar  8 06:22:32 mail postfix/smtpd[12196]: NOQUEUE: reject:
# RCPT from unknown[201.230.203.167]: 554 5.7.1 <unknown[201.230.203.167]>:
# Client host rejected: Access denied; from=<diplomadosprogramas8@yahoo.es>
# to=<info@summan.com> proto=SMTP helo=<192.168.1.20>
function SearchArgument(){
    if [[ $IP != "" ]]; then
        echo $IP
        return 0
    else
        echo "Argumento no encontrado!"
    fi
    return 1
}

# 2. busca la ip correspondiente al domino encontrado en la base de datos
# de spammers. "/opt/zimbra/conf/postfix_rbl_ip_spammers", y la borra.
function DeleteIPFSpammers() {
    sed '/^'$IP'/d' $PostPath/$FSpammers > $PostPath/fspam.tmp
    cat $PostPath/fspam.tmp > $PostPath/$FSpammers
    rm -f $PostPath/fspam.tmp
}

# 3. agrega la ip en la base de datos postfix_rbl_whitelist.
function AddIPWhitelist() {
    echo $IP >> $PostPath/$FWhitelist
}

# 4. regenera la base de datos de spammers
# "postmap /opt/zimbra/conf/postfix_rbl_ip_spammers".
function ReloadDBSpammers() {
    su - zimbra -c "rm -f $PostPath/$DBSpammers"
    su - zimbra -c "postmap $PostPath/$FSpammers"
}

# 5. recargar la base de datos "zmmtactl restart"
function RestartMta() {
    su - zimbra -c "zmmtactl restart"
}

function DeleteLock() {
    rm -f $LOCK_FILE
}


if SearchArgument ; then
   echo "Procesando dominio $1 con la IP: $IP"
   DeleteIPFSpammers
   AddIPWhitelist
   ReloadDBSpammers
   RestartMta
   DeleteLock
else
   echo "Argumento $1 no encontrado!"
fi

# flock END
  else
    echo "$BASE_NAME: Another instance is currently running."
  fi
)

Código fuente: spammers.sh whitelist.sh

En este script utilice un poco de expresiones regulares, funciones como le llama mi compañero +Víctor Daniel "El segundo nivel de bash", condicionales  etc. La forma de utilizarlo es ejecutando y entregando el argumento a utilizar, como por ejemplo dominio ó email.

Espero que a alguien le sirva estos scripts o le ayuden a construir otros, si tiene alguna sugerencia de como mejorarlos por favor dejen sus comentarios.

sábado, 4 de mayo de 2013

Bienvenidos a este blog para principiantes en Linux y BashScript

Soy una persona amante de los retos, y como todo en este mundo siempre hay retos que superar. No soy un desarrollador de software, pero gracias a que hoy en día mis ingresos llegan del mundo opensource (Linux) decidí que era necesario aprender a crear script en bash para automatizar algunas tareas.

Ya se preguntaran... y como hace una persona que no conoce de lógica de programación crear script en bash?.. pues con mucho esfuerzo!!! jajaja... la verdad mi método fue leer tutoriales, manuales de linux (test, sed, awk, cut, bash, grep, etc), recibir tips de genios en bash ( +Víctor Daniel  - Compañero de trabajo) y lo que más me a ayudado es leer script que encuentro en internet.

Publicare algunos de mis pinito que a mi parecer funcionan muy bien, espero que con ayuda de la comunidad pueda llegar a perfeccionarlos y seguir aprendiendo.