giovedì 21 agosto 2008

Estetica Bash

Da così...
#!/bin/bash
found_in_application_xml=$(grep ProjectName /bea/one/9/923/apps/BEdomain/BHcluster/ear/h2o/BHapp/app/META-INF/application.xml)
if [ -n "$found_in_application_xml" ]; then
echo "/bea/one/9/923/apps/BEdomain/BHcluster/ear/h2o/BHapp/app/META-INF/application.xml: OK"
else
echo "/bea/one/9/923/apps/BEdomain/BHcluster/ear/h2o/BHapp/app/META-INF/application.xml: ProjectName not found"
sed -i 's/<\/application>/<module><ejb>ejb\/ProjectName\/ejb20_BH_ProjectName_81.jar<\/ejb><\/module>\n<\/application>/' /bea/one/9/923/apps/BEdomain/BHcluster/ear/h2o/BHapp/app/META-INF/application.xml
fi
found_in_log4j=$(grep projectname /bea/one/9/923/system/BEdomain/BHcluster/log4j.properties)
if [ -n "$found_in_log4j" ]; then
echo "/bea/one/9/923/system/BEdomain/BHcluster/log4j.properties: OK"
else
echo "/bea/one/9/923/system/BEdomain/BHcluster/log4j.properties: projectname not found"
echo "
log4j.appender.PROJECTNAME=org.apache.log4j.FileAppender
log4j.appender.PROJECTNAME.File=/log/projectname.log
log4j.appender.PROJECTNAME.layout=org.apache.log4j.PatternLayout
log4j.appender.PROJECTNAME.layout.ConversionPattern=[%t] [%d{DATE}] - %c -%p: %m%n
log4j.logger.it.sella.projectname=INFO, PROJECTNAME" >> /bea/one/9/923/system/BEdomain/BHcluster/log4j.properties
fi
found_in_integrazione_sistemi_esterni_properties=$(grep ProjectName /bea/one/9/923/system/BEdomain/BHcluster/subSystem.properties)
if [ -n "$found_in_integrazione_sistemi_esterni_properties" ]; then
echo "/bea/one/9/923/system/BEdomain/BHcluster/subSystem.properties: OK"
else
echo "/bea/one/9/923/system/BEdomain/BHcluster/subSystem.properties: ProjectName not found"
echo "
#<ProjectName>
Service.SomeSystem.serviceType=ejb
Service.SomeSystem.xmlStrategy=./data/ProjectName/subsystem.xml
Service.TestSomeSystem.serviceType=ejb
Service.TestSomeSystem.xmlStrategy=./data/ProjectName/ise/ise_TestSomeSystem.xml
#</ProjectName>" >> /bea/one/9/923/system/BEdomain/BHcluster/subSystem.properties
fi
found_in_do_post_contabilizzazione_properties=$(grep projectname /bea/one/9/923/system/BEdomain/BHcluster/OtherSubSystem.properties)
if [ -n "$found_in_do_post_contabilizzazione_properties" ]; then
echo "/bea/one/9/923/system/BEdomain/BHcluster/OtherSubSystem.properties: OK"
else
echo "/bea/one/9/923/system/BEdomain/BHcluster/OtherSubSystem.properties: projectname not found"
echo "
#<ProjectName>
DEB03=it.home.projectname.lib.Class
DEB05=it.home.projectname.lib.Class
#</ProjectName>
" >> /bea/one/9/923/system/BEdomain/BHcluster/OtherSubSystem.properties
fi


a così:
#!/bin/bash
PROJECTNAME="ProjectName"
BEADIR="/bea/one/9/923"

BH_JAR_NAME="ejb20_BH_${PROJECTNAME}_81.jar"
MODULEPATH="ejb/$PROJECTNAME/"

APPLICATION_XML="${BEADIR}/apps/BEdomain/BHcluster/ear/h2o/BHapp/app/META-INF/application.xml"

LOG4JFILE="${BEADIR}/system/BEdomain/BHcluster/log4j.properties"
DOPOSTFILE="${BEADIR}/system/BEdomain/BHcluster/OtherSubSystem.properties"
ISEFILE="${BEADIR}/system/BEdomain/BHcluster/subSystem.properties"



function searchIn() {
FILE="$1"
SUBSTRING="$2"
GREPOPTS="$3 $4 $5 $6 $7 $8 $9"
grep -q $GREPOPTS $SUBSTRING $FILE
return
}

function stringForSed() {
echo "${1//\//\\/}"
}

function addEjbModuleToXml() {
MODULE=$1
XMLFILE=$2
APPLICATION_TAG="</application>"
EJB_TAG="<module><ejb>$MODULE</ejb></module>"
sed -i "s/$(stringForSed $APPLICATION_TAG)/$(stringForSed $EJB_TAG)\n$(stringForSed $APPLICATION_TAG)/g" $XMLFILE
}

function log4j_properties() {
FILENAME="$1"
cat >>"$FILE" <<EOF
log4j.appender.PROJECTNAME=org.apache.log4j.FileAppender
log4j.appender.PROJECTNAME.File=/log/projectname.log
log4j.appender.PROJECTNAME.layout=org.apache.log4j.PatternLayout
log4j.appender.PROJECTNAME.layout.ConversionPattern=[%t] [%d{DATE}] - %c -%p: %m%n
log4j.logger.it.sella.projectname=INFO, PROJECTNAME
EOF
}

function subSystem_properties() {
FILENAME="$1"
cat >>"$FILE" <<EOF
#<ProjectName>
Service.SomeSystem.serviceType=ejb
Service.SomeSystem.xmlStrategy=./data/ProjectName/subsystem.xml
Service.TestSomeSystem.serviceType=ejb
Service.TestSomeSystem.xmlStrategy=./data/ProjectName/ise/ise_TestSomeSystem.xml
#</ProjectName>
EOF
}

function OtherSubSystem_properties {
FILENAME="$1"
cat >>"$FILE" <<EOF
#<ProjectName>
DEB03=it.home.projectname.lib.Class
DEB05=it.home.projectname.lib.Class
#</ProjectName>
EOF
}


if ! searchIn "$APPLICATION_XML" "$BH_JAR_NAME"; then
echo "Adding $BH_JAR_NAME in $APPLICATION_XML"
addEjbModuleToXml "$MODULEPATH/$BH_JAR_NAME" $APPLICATION_XML
fi


for FILE in $LOG4JFILE $DOPOSTFILE $ISEFILE; do
if ! searchIn "$FILE" $PROJECTNAME "-i"; then
appenderName="$(basename "$FILE")"
echo "Updating $FILE..."
${appenderName//./_} "$FILE"
fi
done

giovedì 17 luglio 2008

Actions handler via filesystem monitoring

Avendo avuto la necessità di eseguire degli script bash che eseguono il riavvio di servers Weblogic senza avere a disposizione una shell da cui lanciarli abbiamo pensato le più disparate possibilità, ivi compreso smanettare tutto il giorno sulla console di Weblogic, progettare applicazioni standalone jmx, pagine jsp apposite.. oggi pomeriggio mi sono reso conto che in realtà tutto ciò che serve è un crontab funzionante.
Basta creare uno script shell lanciato ripetutamente da quel crontab (tipo ogni minuto) e che controlla l'esistenza di determinati files per lanciare azioni ad essi associate (e cancellare il file che ha scatenato l'azione).
Durante qualche ritaglio di tempo nelle pause ecco cos'è uscito fuori:
#!/bin/bash                  

#ACTIONSDIR="/tmp/actions"
ACTIONSDIR="/nodel/actions"
ACTIONSCRIPTSDIR="$ACTIONSDIR/scripts"
ACTIONS="restart-admin restart-batch crontab"

function doAction() {
action="$1"
actionfile="$ACTIONSDIR/$action"
actionscript="$ACTIONSCRIPTSDIR/${action}.sh"
if [ -r $actionfile.lock ]; then return; fi
echo "`date`: running action $action with script file $actionscript" > $actionfile.lock
echo "doing action $action (script file: $actionscript)"
chmod +x $actionscript
$actionscript $action $actionfile
rm $actionfile
rm $actionfile.lock
}

function createDir() {
dirToCreate=$1
if [ -d $dirToCreate ]; then
return
fi
mkdir -p $dirToCreate
}

createDir $ACTIONSDIR
createDir $ACTIONSCRIPTSDIR

for action in $ACTIONS; do
actionfile=$ACTIONSDIR/$action
if [ -r $actionfile ]; then
doAction $action &
fi
done



Un paio di commenti:
  • Per aggiungere/rimuovere azioni basta modificare la variabile ACTIONS e aggiungere gli script nella directory adeguata (specificata da ACTIONSCRIPTSDIR)
  • gli script vengono lanciati in maniera asincrona dal loop principale, ma in maniera sincrona nel doAction, in modo tale da cancellare il file di lancio solo dopo il termine dello script. Un file di lock impedisce di rilanciare l'azione se è ancora in esecuzione.
  • Il file di lancio viene passato come argomento (insieme al nome dell'azione) allo script. Questo permette di inserire un target come "crontab", che potrebbe essere usato per aggiornare il crontab appunto leggendo dal file di lancio il nuovo cron da installare.

sabato 12 luglio 2008

Fast Scripting Tool

Spesso per risolvere determinati problemi d'ordine quotidiano mi capita di creare piccolo script shell appositi, da buon maniaco della linea di comando.
La procedura per creare uno script può risultare relativamente noiosa: creare un file con touch, renderlo eseguibile con chmod, modificarlo col proprio editor preferito, specificare in cima l'interprete ("#!/bin/bash" di solito)... ed è sempre la stessa solfa, piuttosto pallosa.
Soluzione: mi sono scritto uno script bash per creare altri script bash.
Ho anche fatto in modo di parametrizzarlo: il primo parametro è lo script da creare, il secondo l'interprete (opzionale, se non specificato di default va su "/bin/bash".
Ecco lo script, da piazzare magari in /usr/local/bin in modo da averlo nel path:
#!/bin/bash
function usage() {
echo "Usage: `basename $0` filename [interpreter path]"
exit 0
}


if test "x$1" == "x"; then
usage
fi

INTERPRETER="/bin/bash"

if test "x$2" != "x"; then
if ! [ -r $2 ]; then
echo "Error! Interpreter \"$2\"not found"
usage
else
INTERPRETER="$2"
fi
fi

cat >$1 <<EOF
#!$INTERPRETER

EOF

chmod +x $1
vim $1 +2




L'ultima riga in particolare apre vim, specificandogli anche su che riga piazzarsi.. per la precisione dopo la seconda, subito dopo la dichiarazione dell'interprete (così non si fa neanche la fatica di premere freccia-giù :P)

venerdì 11 luglio 2008

Paginazione in Oracle

A differenza di database come MySQL, in oracle la paginazione dei dati non è così elementare..
Esiste un campo interno ROWNUM che in effetti numera le righe del risultato di una query.
Il problema però è che la numerazione inizia dopo l'invocazione di rownum, non prima, ergo un'espressione come:
select * from ourTable where rownum>2;

non può funzionare, perchè la prima riga (rownum=1) non verrà mai visualizzata, e di conseguenza rownum non verrà mai incrementato.
La soluzione è effettuare tre nested query: la prima con la query alla tabella da noi desiderata, la seconda che limita la finestra all'offset superiore della paginazione, la terza che forza il limite inferiore, trattando rownum come una normale colonna di una tabella.
Ecco come:
select * from
(select ourTable.*, rownum rowN from
(select * from ourTable
where ourCondition=true
order by ourColumn)
where rownum <= maxPageOffset)
where rowN >= minPageOffset;

Reprise

Essì prima o poi sarebbe anche il caso di tornare a scrivere qualcosa...

giovedì 24 gennaio 2008

Ho bisogno di un basso..


No.. non quel basso (anche perchè con la crisi di governo in corso mi sa che ce lo ritroveremo comunque molto presto..)
Ormai non suono da più di dieci giorni, e si sente.. mi sento le dita piuttosto "addormentate", avrei bisogno di esercitarmi almeno un po' col mio caro quattrocordofono.. Pazienza.
Sembra che le cose al lavoro si stiano muovendo un po', domani mattina ho un nuovo colloquio.. sperem! (anche perchè se pagano bene chissà che non ci possa comprare un basso nuovo.. ;) )

domenica 20 gennaio 2008

Vita Milanese

Vita milanese si fa per dire...
Primi giorni chiuso in casa, vuoi per il freddo, vuoi per il raffreddore, vuoi perchè non ho nulla da fare fuori (e mi scoccia andare in tram a vuoto).

Però aspetto con ansia il 25.. Trio Bobo alla Salumeria della Musica :)
Non posso suonare il basso, ma almeno potrò ascoltare il mio bassista preferito :P