Newsgroup: it.comp.os.linux.iniziare
Titolo: [Bash] Formattare una riga di testo in modo personalizzato

Ciao,
Tanto per esercitarmi nell'uso della shell e dei suoi strumenti avevo
pensato di scrivere uno script che prendendo in input i log del mio
firewall costruito con iptables mi riportasse in un altro file solo i
dati che ritengo interessanti.
So che esistono strumenti che si occupano di analizzare i log, ma vorrei
fare esercizio per capire come estrarre da una riga di testo solo le
informazioni che mi interessano e scartare le altre.
Per esempio una tipica linea di log potrebbe essere questa:
Nov 14 02:41:15 portatile kernel: IN=lo OUT=
MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1
DST=127.0.0.1 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=22509 DF PROTO=TCP
SPT=33040 DPT=119 WINDOW=32767 RES=0x00 SYN URGP=0
io a questo punto vorrei estrarre solo i dati riguardanti:
- Data e ora
- IN
- OUT
- SRC
- DST
- PROTO
- SPT
- DPT
Avevo pensato di usare 'sed' oppure 'awk' però sinceramente sono davvero
complicati (almeno per me).
In alternativa si potrebbe usare il perl (qualcuno conosce un manuale
introduttivo in italiano?), però non lo conosco !!! :-(
Vi chiedo solo di darmi una dritta per impostare il lavoro, non la
soluzione, a quella mi piacerebbe arrivare da solo...
grazie mille :-)
-- 
   ("`-''-/").___..--''"`-._
    `6_ 6  )   `-.  (     ).`-.__.`)
    (_Y_.)'  ._   )  `._ `. ``-..-'
  _..`--'_..-_/  /--'_.' ,'
(il),-''  (li),'  ((!.-'

Grazie lo stesso, ho risolto con un po di 'grep' 'vim -c' 'cut -d -f'.
Se avete qualche altra soluzione magari in perl sarei felice di
sentirla, giusto per capirne qualcosina in più su questo linquaggio.
ciao a tutti :-)


  dati che ritengo interessanti.
#!/bin/sh
# Paolo Pedaletti
# paolop[]
matapp.unimib.it
# 2000/02/22
# LOG analyzer (firewall log in this case)
if [ ! $UID = 0 ] ; then
	echo "You are not root, sorry"
	exit 1
fi
RESOLV="yes"
#RESOLV="no"
IFSold=$IFS
IFS=' '
# a causa di `host` diversi... in resolvhost
LINUX=debian
#LINUX=rh
PROGRAM=/root/script/iptables-analyze.sh
DESC="iptables analizer"
NAME=iptables-analyze.sh
PIDFILE=/var/run/${NAME}.pid
EVENTFILE=/var/log/syslog
LOGFILE=/var/log/iptables.log
LOGTTY=/dev/tty11
DATEFMT="%Y-%m-%d %H:%M"
test -f $PROGRAM || (echo "$PROGRAM not found"; exit 0)
case "$1" in 
	start|on|1)
		if [ -e $PIDFILE ] ; then
			echo "sorry, $PROGRAM is already running ...(${PIDFILE})"
			exit 1 
		else
			echo "`date +"$DATEFMT"` : ok, starting $NAME : $DESC ..." >> $LOGTTY
			FWPID=$$
			echo $FWPID > $PIDFILE
		fi
		;;
	stop|off|0)
#		if [ -e $PIDFILE ] ; then
			echo "`date +"$DATEFMT"` : ok, terminating $NAME : $DESC ..." >> $LOGTTY
			rm -f $PIDFILE
			PIDS=`ps aux | grep firewall-analyze.sh | grep -v grep | cut -b 8-15` 
			echo $PIDS
			kill -KILL $PIDS 
			exit 0
		;;
	reload|restart|force-reload)
		echo -n "Restarting $DESC: $NAME"
		$0 stop
		sleep 3
		$0 start
	;;
	*)
		echo "Usage: $0 {start|stop|restart}"
		exit 1
	;;
esac
EVENTFILE=${2:-$EVENTFILE}
echo -n "$EVENTFILE -> "
LOGFILE=${3:-$LOGFILE}
echo "$LOGFILE"
if [ ! -f $LOGFILE ] ; then
	/bin/touch $LOGFILE
	/bin/chmod 640 $LOGFILE
fi
# rm lockfile when CTRL-C ...
trap " rm -f $PIDFILE; IFS=$IFSold ; echo \"`date +"$DATEFMT"` : ok, $PIDFILE deleted\" | tee -a $LOGTTY" 0 
#1 2 5 15
port2service() {
# see /etc/services
	case $1 in
		7)                 SERVICE="ECHO";;
		20|21)             SERVICE="FTP";;
		22)                SERVICE="SSH";;
		23)                SERVICE="TELNET";;
		25)                SERVICE="SMTP";;
		37)                SERVICE="TIME";;
		53)                SERVICE="DNS";;
		67)                SERVICE="BOOTPSserver";;
		68)                SERVICE="BOOTPSclient";;
		69)                SERVICE="TFTP";;
		79)                SERVICE="FINGER";;
		80)                SERVICE="HTTP";;
		110)               SERVICE="POP3";;
		111)               SERVICE="SUNRPC";;
		113)               SERVICE="AUTH";;
		119)               SERVICE="NNTP";;
		123)               SERVICE="NTP";;
		13[789])           SERVICE="NETBIOS";;
		143)               SERVICE="IMAP2";;
		194)               SERVICE="IRC";;
		443)               SERVICE="HTTPS";;
		698)               SERVICE="OLSR";;
		615)               SERVICE="sco-inetmgr";;
		617)               SERVICE="sco-dtmgr";;
		621)               SERVICE="escp-ip";;
		684)               SERVICE="corba-iiop-ssl";;
		688)               SERVICE="realm-rusd";;
		704)               SERVICE="elcsd";;
		772)               SERVICE="cycleserv2";;
		888)               SERVICE="accessbuilder/cddbp";;
		102[0-3])          SERVICE="SSH";;
		1433)              SERVICE="MS-SQL";;
		2049)              SERVICE="2049";;
		4000)              SERVICE="ICQ";;
		8080)              SERVICE="HTTPproxy";;
		5999|600[0-3])     SERVICE="X";;
		7100)              SERVICE="X-FontServer";;
		3133[7-8])         SERVICE="BACKORIFICE";;
		12345|12346|20034) SERVICE="NETBUS";;
		*)                 SERVICE="$1";;
	esac
	echo $SERVICE
}
icmp2service() {
# Valid ICMP Types, from ipchains -h icmp
	case $1 in
		0)   SERVICE="echo-reply (pong)";;
		1)   SERVICE="destination-unreachable";;
		2)   SERVICE="source-quench";;
		3)   SERVICE="redirect";;
		4)   SERVICE="echo-request (ping)";;
		5)   SERVICE="router-advertisement";;
		6)   SERVICE="router-solicitation";;
		7)   SERVICE="time-exceeded";;
		8)   SERVICE="parameter-problem";;
		9)   SERVICE="timestamp-request";;
		10)  SERVICE="timestamp-reply";;
		11)  SERVICE="address-mask-request";;
		12)  SERVICE="address-mask-reply";;
		*)   SERVICE="$1";;
	esac
	echo $SERVICE
}
hostresolv() {
	IP=$1
	if [ $LINUX = "debian" ] ; then
# Debian
		HOST=`/usr/bin/host -s 4 $IP 2> /dev/null | /bin/grep "Name: "| /usr/bin/cut -d' ' -f 2`
	else
# RH
		HOST=`/usr/bin/host -s 4 $IP 2> /dev/null | /usr/bin/cut  -d' ' -f 5 `
	fi
	if [ -z "$HOST" ] ; then
		echo "$IP"
	else
		echo "$HOST"
	fi
}
#
/usr/bin/tail -n 50 --pid $FWPID --retry --follow=name ${EVENTFILE} | while read LINE; do
	LOGLINE=`echo $LINE | /bin/grep "FIREW-"`
	if [ ! -z "$LOGLINE" ] ; then	# ok, let's go...
# LOGLINE=
#          Feb 21 01:59:08 niels kernel: Packet log: input     DENY   ppp0  PROTO=6 
1.2.1.5:1
 
1.9.1.9:1
 L=60 S=0x00 I=65324 F=0x4000 T=61 (#4)
#		read MONTH DAY TIME  HOST  NULL    NULL   NULL DIRECTION CHAIN IFACE PROTO   FROM       TO        LEN ToS    IPID    FRAGMENT TTL  NCHAIN <<EODATA
		read MONTH DAY TIME  HOST  KERNEL CHAIN NULL <<EODATA
$LOGLINE
EODATA
		NEWLINE=`echo "$LOGLINE" | tr ' ' "\n"`
#		echo "--- $NEWLINE --- "
		PROTO=`echo $NEWLINE|grep PROTO=`	; PROTO=${PROTO##*=}
		SRC=`  echo $NEWLINE|grep SRC=` 		; SRC=${SRC##*=}
		DST=`  echo $NEWLINE|grep DST=`		; DST=${DST##*=}
		SPT=`  echo $NEWLINE|grep SPT=`		; SPT=${SPT##*=}
		DPT=`  echo $NEWLINE|grep DPT=`		; DPT=${DPT##*=}
		IN=`   echo $NEWLINE|grep IN=`		; IN=${IN##*=}
		if [ "$RESOLV" = "yes" ] ; then
			HOSTFROM=`hostresolv $SRC`
			HOSTTO=`hostresolv $DST`
		else
			HOSTFROM=$SRC
			HOSTTO=$DST
		fi
#			echo -e "DF=$DF IN=$IN PROTO=$PROTO SRC=$SRC SPT=$SPT -> DST=$DST DPT=$DPT"
		case $PROTO in
			TCP)
				SERVICEFROM=`port2service $SPT`
				SERVICETO=`port2service $DPT`
				;;
			ICMP)
				SERVICEFROM=`icmp2service $SPT`
				SERVICETO=`icmp2service $DPT`
				;;
			UDP)
				SERVICEFROM=`port2service $SPT`
				SERVICETO=`port2service $DPT`
				;;
			*) echo "non lo so : IN=$IN SRC=$SRC DST=$DST DF=$DF PROTO=$PROTO SPT=$SPT DPT=$DPT"
				echo -e "$LOGLINE \n"
				continue
				;;
		esac
#		REPORT=`printf "%10s %8s %8s %8s %7s" $DATE ${TIME} "${NCHAIN}" ${DIRECTION} ${CHAIN}`
		REPORT=`printf "%s %s %s %5s %4s " ${DAY}${MONTH} ${TIME} ${IN} ${CHAIN} ${PROTO}`
		TMP=`printf "%25s:%5s (%5s) > %25s:%5s (%5s)" $HOSTFROM $SPT $SERVICEFROM  $HOSTTO $DPT $SERVICETO`
		REPORT="$REPORT $TMP"
#		echo "$REPORT"
		echo "$REPORT" >> $LOGFILE
		echo "$REPORT" >> $LOGTTY
		if [ "$SERVICE" = "BACKORIFICE" ] ; then
			if [ "$CHAIN" = "ACCEPT" ] ; then
				play /usr/local/dati/audio/wav/hoihoi.wav
			else
				play /usr/local/dati/audio/wav/evil-laf.wav
			fi
		fi
   fi	# if [ ! -z "$LOGLINE" ]
done	# while read LINE
buon divertimento.
-- 
Pa.Ped, Como
http://www.fastflow.it/~paolop
VOTE AGAINST SPAM! 
http://www.politik-digital.de/spam/it/
Contro i brevetti software: 
http://petition.eurolinux.org/index_html

introduttivo in italiano?), però non lo conosco !!! :-(
Vai avanti su questa strada.
Se il formato delle linee è standard (sempre lo stesso numero di campi e la
posizione relativa tra i vari campi è fissa) con awk il problema diventa
molto semplice, altrimanti "presumo" che possa tornare utile il perl.
Per quel che riguarda la difficoltà non preoccuparti. Se cerchi con Google
trovi diversi documenti su sed e su awk in italiano (qualcosa c'è sul sito
di 
inter.net
).
Io quest'estate avevo una necessità analoga. Mi ero riproposto di lasciar
perdere awk, di imparare direttamente il perl, ma poi mi sono reso conto
che con awk potevo togliere molto facilmente le castagne dal fuoco, e in un
pomeriggio già ero "operativo", partendo *solo* dalla pagina di manuale
(debitamente stampata, mi è più comodo).
N.B. Non sono un programmatore, anche se due script riesco a scriverli,
quindi awk è accessibile.
Anche sugli Appunti linux c'è qualcosa.
Ciao.
-- 
Antonio   @=D

 Buon divertimento
Grazie mille!
Ho adattato lo script alla mia configurazione e funziona davvero bene
con poche modifiche...
ciao e grazie ancora... :-)


 molto semplice, altrimanti "presumo" che possa tornare utile il perl.
Il punto è proprio che il numero di campi è variabile quindi con awk
diventa piuttosto complicato.
All'inizio avevo risolto con 'vim' in modalità non interattiva per
portare le righe ad un formato standard, poi con 'cut' le dividevo in
campi e stampavo un report in un file.
In seguito mi sono studiato un pochino di 'python' e in pochissime righe
di codice ho risolto il problema.
Non conosco il perl, ma devo dire che python mi sta entusiasmando per la
facilità con cui si riescono a scrivere script di shell da usarsi nelle
più disparate occasioni, è un linguaggio molto elegante e neanche
difficile da imparare(almeno le basi che ho visto sino ad ora)...
ciao e grazie per il tuo aiuto :-)
