Kleine und große Linux AHAs
Ronny
Dieser Benutzer hat keine Details eingegeben.
Beiträge von Ronny
syslog-ng und “last message repeated NN times”
07. Mai
Auch danach musste ich länger suchen. Wir betreiben einen zentralen Syslogserver mit Hilfe von Syslog-NG. Darauf loggen auch “nicht Linux” Systeme. Dabei geht es überwiegend um Security Meldungen die über die Datenbank dann ausgewertet werden, bzw. für Alarmierungen genutzt werden.
Bei Änderungen im zentralen Directory kann es unter Umständen zu mehreren hunderttausend Logeinträgen in der Stunde kommen (wir hatten auch schon knapp 1 Mio.). Das ist kein Problem für syslog-ng oder für die Datenbank. Allerdings für die Scripte die über die Datenbank laufen um irgendwelche Auffälligkeiten zu finden / melden.
Im “alten” original syslogd gab es früher immer Meldungen wie “last message repeated XX times”. Die gibt es standardmäßig im syslog-ng nicht und der Parameter ist auch nicht in der Manpage dokumentiert. Man kann ihn aber einschalten
Der Parameter heißt “suppress(X)“. Als Parameter wird die Zeit in Sekunden übergeben, die Syslog-NG warten soll ob noch weitere Meldungen mit gleichem Inhalt den Server erreichen. Der Parameter wird in der Destination mit angegeben. Das ganze sieht bei uns so aus:
destination d_mysql_win {
pipe("/var/run/phpsyslog_win.pipe"
template("INSERT INTO logs
(host, facility, priority, level, tag, datetime, program, msg)
VALUES ( '$HOST', '$FACILITY', '$PRIORITY', '$LEVEL', '$TAG', '$YEAR-$MONTH-$DAY $HOUR:$MIN:$SEC',
'$PROGRAM', '$MSG' );\n") template-escape(yes) suppress(30));
};
perl daemon mit input aus einer named pipe
07. Mai
Auch sowas wo ich lange nach gesucht habe. Möchte man, dass ein Perl Programm den Input einer named pipe verarbeitet, so wird man als erstes auf ein Problem stossen. Das Programm wird sich nach jeder Eingabe beenden. Mein erster Code sah zum Beispiel so aus:
#!/usr/bin/perl -w
open(THISPIPE, ") {
echo $_;
}
close THISPIPE;
So würde wohl jeder erste Versuch aussehen. Das Problem liegt darin, dass sobald Daten über die Pipe ausgetauscht werden, auch ein EOF mitgegeben wird. Dieses EOF wird von Perl als solches auch interpretiert und die Datei wird geschlossen.
Umgehen kann man das, indem man einen Trick anwendet und die Datei nicht nur zum lesen öffnet, sondern zum Lesen und Schreiben. Dadurch wird die Datei nicht nach einem EOF geschlossen und der Daemon lauscht weiterhin auf der Pipe. Das sieht dann so aus:
#!/usr/bin/perl -w
open(THISPIPE, "+) {
echo $_;
}
close THISPIPE;
switchport per tcpdump bestimmen
05. Mai
Das unter Cisco verfügbare CDP Protokoll (Cisco Discovery Protocol) kann man nutzen – wenn eingeschaltet – um den Port zu bestimmen, an dem ein Server angeschlossen ist. Dazu muss man lediglich per tcpdump das CDP Paket empfangen und anzeigen. Der Rest ist an sich verständlich.
tcpdump -nn -v -i -s 1500 -c 1 'ether[20:2] == 0x2000'
Der Output dazu sieht dann beipielsweise so aus:
tcpdump: listening on bond0, link-type EN10MB (Ethernet), capture size 1500 bytes
15:16:16.901794 CDPv2, ttl: 180s, checksum: 692 (unverified), length 364
Device-ID (0x01), length: 8 bytes: 'SWITCH1'
Version String (0x05), length: 251 bytes:
Cisco IOS Software, Catalyst 4000 L3 Switch Software (cat4000-I5S-M), Version 12.2(25)EWA7, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2006 by Cisco Systems, Inc.
Compiled Mon 16-Oct-06 18:52 by dchih
Platform (0x06), length: 14 bytes: 'cisco WS-C4948'
Address (0x02), length: 13 bytes: IPv4 (1) 192.168.151.2
Port-ID (0x03), length: 19 bytes: 'GigabitEthernet1/27'
Capability (0x04), length: 4 bytes: (0x00000029): Router, L2 Switch, IGMP snooping
VTP Management Domain (0x09), length: 2 bytes: ''''
Native VLAN ID (0x0a), length: 2 bytes: 157
Duplex (0x0b), length: 1 byte: full
AVVID trust bitmap (0x12), length: 1 byte: 0x00
AVVID untrusted ports CoS (0x13), length: 1 byte: 0x00
1 packets captured
1 packets received by filter
0 packets dropped by kernel
Daraus lässt sich der Switchname (SWITCH1) herauslesen, der Port (GigabitEthernet1/27) und auch die VLAN ID (157) uvm. Wenn das Interface per Bonding betrieben wird, bekommt man hiermit lediglich die Information des aktiven Ports.
Lotus Notes 8.5 unter Ubuntu, Attachment öffnen
05. Mai
Um mit Notes 8.5 ein Attachment direkt öffnen zu können, muss man folgende Datei anpassen:
Datei: /opt/ibm/lotus/notes/openwith
#!/bin/bash
# Öffnet die entsprechende Datei, die als Parameter übergeben wird
if test -f "$1"
then
/usr/bin/xdg-open "$1"
fi
exit 0
Lotus Notes 8.5 unter Ubuntu, Schriften
05. Mai
Damit die Schriften “hübsch” sind, muss das Paket ttf-xfree86-nonfree installiert sein.
grep ohne grep
04. Mai
In vielen Scripten wird grep genutzt um den Inhalt eines Strings / einer Variablen innerhalb eines Shell Scripts zu prüfen. So etwas sieht dann schnell so aus (nur eine der Möglichkeiten):
test=blah
ret=`echo $test | grep -q la`
if [ $ret != 0 ]
then
echo "nicht gefunden"
else
echo "gefunden"
fi
Das ganze würde jedoch – wenigstens in dieser einfachen Form – auch anders gehen:
if [[ "$test" =~ "la" ]]
then
echo "ja"
fi
Der Vorteil dieser Lösung ist, dass kein weiterer Prozess für die Prüfung notwendig ist und das ganze somit um einiges schneller ist.
Zufallszahlen mit der Bash
01. Mai
Ganz einfach – wenn man es mal gesehen / gefunden hat:
echo $((RANDOM % 100))
Das ergibt eine Zahl zwischen 0 und 100.
Möchte man lediglich die Zahlen zwischen 1 und 100 haben, so reicht diese kleine Änderung
echo $((RANDOM % 100 +1))
Das ganze ist ganz interessant für cronjobs. Viele Rechner sollen irgendwas machen, aber am besten nicht alle genau gleichzeitig. Also:
#
0 12 * * * root sleep $(( RANDOM \% 60 )); echo "blah"
Dieser Job würde dann zwischen 12:00 und 12:01 laufen. Wichtig dabei ist das maskierte Prozentzeichen – ansonsten funktioniert das ganze nicht.
Bash Jobs Parallelisieren
29. Apr
Es gibt Anforderungen bei denen es nötig ist viele Befehle – möglicherweise mit verschiedenen Parametern – schnell ab zu arbeiten. Dabei kann man sich der Anzahl an Cores in einem Server (oder auch PC) bedienen. Eine Anforderung wäre zum Beispiel, dass immer so viele Prozesse gestartet werden, wie auch Prozessoren verfügbar sind. Das ganze möglichst ohne viel Drumherum – also ohne viel Installationsaufwand.
Eine ganz simple Möglichkeit stellt folgendes Script dar. Als Parameter wird jeweils der komplette Befehl angegeben. Standardmäßig laufen immer so viele Prozesse gleichzeitig wie Prozessoren vorhanden sind. Diese Zahl kann aber auch manuell vorgegeben werden. Das restliche Management übernimmt das Script selbst.
#!/bin/bash
#
# Ronny Becker, 05.2009
#
NUM=0
QUEUE=""
MAX_NPROC="none"
USAGE="A simple wrapper for running processes in parallel.
Usage: `basename $0` [-h] [-q] [-r] [-j nb_jobs] command command command command command command command command ...
-h Shows this help
-j nb_jobs Set number of simultanious jobs [def. CPU Count]
-q be quiet - do not output any information (but errors)
Examples:
`basename $0` somecommand somecommand somecommand ..."
# subs
function queue {
QUEUE="$QUEUE $1"
NUM=$(($NUM+1))
}
function regeneratequeue {
OLDREQUEUE=$QUEUE
QUEUE=""
NUM=0
for PID in $OLDREQUEUE
do
if [ -d /proc/$PID ] ; then
QUEUE="$QUEUE $PID"
NUM=$(($NUM+1))
fi
done
}
function checkqueue {
OLDCHQUEUE=$QUEUE
for PID in $OLDCHQUEUE
do
if [ ! -d /proc/$PID ] ; then
regeneratequeue # at least one PID has finished
break
fi
done
}
# parse command line
if [ $# -eq 0 ]; then # must be at least one arg
echo "$USAGE" >&2
exit 1
fi
while getopts j:qh OPT; do # "j:" waits for an argument "h" doesnt
case $OPT in
h) echo "$USAGE"
exit 0 ;;
j) MAX_NPROC=$OPTARG ;;
q) BE_QUIET=1 ;;
\?) # getopts issues an error message
echo "$USAGE" >&2
exit 1 ;;
esac
done
# get cpu information (cpu count = MAX_NPROC)
if [[ "$MAX_NPROC" =~ "none" ]]; then
CPUs=`cat /proc/cpuinfo | grep -c "processor.*[0-9]$" 2>/dev/null`
if [ $CPUs -gt 0 ]
then
MAX_NPROC=$CPUs
if [ ! $BE_QUIET ]; then echo "Found $MAX_NPROC CPUs - using $MAX_NPROC parallel threads"; fi
else
MAX_NPROC=2
if [ ! $BE_QUIET ]; then echo "Setting number of simultanous jobs to 2 - could not get CPU information"; fi
fi
fi
# Main program
shift `expr $OPTIND - 1` # shift input args, ignore processed args
# Count all Jobs
CMD_COUNT=$#
CMD_COUNT_ACT=0
# run forest run !!
while [ $# -gt 0 ] # for the rest of the arguments
do
# statistics
CMD_COUNT_ACT=$(($CMD_COUNT_ACT + 1))
# define command
CMD="$1"
shift
if [ ! $BE_QUIET ]; then echo -e "`date \"+%d.%m.%Y %H:%M:%S\"`: \033[1m [${CMD_COUNT_ACT}/${CMD_COUNT}]\033[0m Starting \033[1m${CMD}\033[0m"; fi
# run command
eval "$CMD &"
PID=$!
queue $PID
while [ $NUM -ge $MAX_NPROC ]; do
checkqueue
sleep 0.6
done
done
wait # wait for all processes to finish before exit
if [ ! $BE_QUIET ]; then echo -e "`date \"+%d.%m.%Y %H:%M:%S\"`: \033[1m all procs finished \033[0m"; fi
Das Original Script funktioniert ein wenig anders. Zu finden ist es hier
Da sind wir!
23. Mrz
Wir ? Das sind zwei. Ronny und Sascha. Wir sind Linux Admins und möchten auf dieser Seite von uns genannte “AHAs” sammeln. Unsere AHAs sind zum Beispiel kleine Code Scnippets, Tipps oder HowTos die alle mit Linux zu tun haben.
|
|
Unsere AHAs sind allerdings nicht einfach eine weitere Sammlung wie es schon so viele gibt. Wir möchten an dieser Stelle Informationen sammeln die wir selbst lange suchen mussten. Mal schauen was daraus wird … |




