Howto: Backupmailbox – ein Kochrezept

Das Problem: ein Backup von wenigen aber wichtigen kleinen Dateien von einem Server machen, aber irgendwie keine Zeit den eigentlichen Backup-Client einzurichten. Sowieso ist in diesem Fall der Backup-Client auf dem Server eigentlich ein bisschen wie mit Kanonen auf Spatzen zu schiessen. Backup muss aber dennoch gemacht werden.

Die Loesung: die Backupmailbox. Auf dem Mailserver wird eine Backup-Aliasmailadresse eingerichtet. Backups gehen dann per Mail an diese Adresse, ein Skript extrahiert die Anhaenge und legt sie im Dateisystem in einer Ordnerstruktur ab. Diese Ordner werden dann ueber den Backupclient – der auf dem Mailserver sowieso laeuft – mit ins regulaere Backup geschoben. Die Anhaenge werden in Unterordner gespeichert, die dem Namen der EMailadresse entsprechen um sie besser auseinanderzuhalten. Dabei wird das @ gegen einen . ersetzt. Weiter werden nur Emails bearbeitet, die als Betreff ein definiertes Zufallspasswort haben.

Die Umsetzung: Man benoetigt einen Email-Alias, ein Skript, zwei Ordner im Dateisystem, ein Zufallspasswort und 15min Zeit eines Systemadministrators.

Zuerst lege man in der /etc/aliases einen neuen Backup-Alias an:

backupalias: "| /path/to/attatchExtract.sh"

und uebernehme diesen mit dem Kommando newaliases. Danach lege man unter dem definierten Pfad das folgende Skript ab:

#!/bin/bash
 
## base path where attachments and logfile should be stored without trailing slash
BASEPATH=/var/local/backup/
 
 
## The subject needs to match this string, otherwise the mail is dropped without action
SECRETSUBJECT="12345"
 
 
## uniq filename for temp file
FILENAME=$(date +%s)
echo "Filename = $FILENAME" >> $BASEPATH/logfile
 
 
## safe email to tmp file
/bin/cat > /tmp/$FILENAME
 
 
## extract sender from email
SENDER=$(grep "From:" /tmp/$FILENAME | sed 's/.*< *//;s/ *>.*//' | tr "@" ".")
echo "Sender = $SENDER" >> $BASEPATH/logfile
 
 
## extract subject from email
SUBJECT=$(grep "Subject:" /tmp/$FILENAME | sed '/^Subject: */!d; s///; q')
echo "Subject = $SUBJECT" >> $BASEPATH/logfile
 
 
## only do something if secret subject is matched
if [ "$SUBJECT" == "$SECRETSUBJECT" ]; then
 
 
  ## create folder for email address if doesn't exist
  if [ ! -d "$BASEPATH/$SENDER" ] ; then
    echo "Directory $BASEPATH/$SENDER does not exist, creating it" >> $BASEPATH/logfile
    mkdir -p $BASEPATH/$SENDER
  fi
 
 
  ## extract files from email and safe to correcet folder
  /usr/bin/uudeview -i -a -p $BASEPATH/$SENDER/ /tmp/$FILENAME >> $BASEPATH/logfile
  echo >> /$BASEPATH/logfile
 
 
## otherwise just do nothing
else
  echo "Subject didn't match secret Subject. Doing nothing..." >> $BASEPATH/logfile
fi
 
 
## delete tmp file
/bin/rm /tmp/$FILENAME

In dem Skript passe man nun das Zufallspasswort gegen ein eigenes an (makepasswd –chars 40) und aktualisiere den BASEPATH. Zuletzt noch das Skript mit chmod 755 ausfuehrbar machen und das Ergebnis aus dem Mailclient seiner Wahl testen.

Sollte es zu Problemen kommen, dass keine Logdatei und Anhaenge abgelegt werden liegt dieses meistens an fehlenden Rechten.

Howto: Apache mit SVN sowie ACL + Migration

Im folgenden ist beschrieben, wie man einen SVN-Server mit HTTP-Zugang einrichtet und anschliessend ein vorhandenes Repository auf diesen neuen Server umzieht. Die Anleitung bezieht sich auf einen Ubuntu Server, es sollte sich jedoch auf Debian Systemen alles analog verhalten.

Zuerst wird die benoetigte Software installiert:

apt-get install subversion libapache2-svn

Danach werden die erforderlichen Ordnerstrukturen angelegt:

mkdir /srv/svn
mkdir /srv/svn/repository
 
chown www-data:www-data /srv/svn/repository
chmod 770 /srv/svn/repository

Als naechstes wird die Datei /etc/apache2/mods-available/dav_svn.conf entsprechend konfiguriert. Hier werden verschiedene Dinge eingestellt, unter anderem fuer die Zugangsbeschraenkungen und ACLs:

<Location /svn>
  DAV svn
  SVNParentPath /srv/svn/repository
  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile /srv/svn/dav_svn.passwd
  AuthzSVNAccessFile /srv/svn/dav_svn.authz
  Require valid-user
</Location>

Nun wird in der /srv/svn/dav_svn.passwd ein neuer Benutzeraccount angelegt, der Zugriff auf das Repository bekommen soll:

htpasswd -c /srv/svn/dav_svn.passwd USERNAME

Und in der /srv/svn/dav_svn.authz die entsprechenden ACL-Rechte gesetzt:

[example:/]
USERNAME = rw

Zum Schluss wird das Repository migriert. Dafuer muss auf dem alten Server ein entsprechender Repository-Dump erzeugt, und auf den neuen Server kopiert werden:

svnadmin dump /path/to/repository/foobar > foobar.dump
scp foobar.dump user@example.net:

Auf dem neuen Server wird nun ein neues Repository angelegt und mit dem vorher erstellten und kopierten Dump befuellt. Damit es die richtigen Rechte hat, wird es als Benutzer www-data gemacht

cd /srv/svn/repository
su www-data
svnadmin create foobar
svnadmin load foobar < foobar.dump

Das wars! Ab nun kann man auf das Repository auf den neuen Server schwenken und damit arbeiten. In diesem Beispielfall koennte es das folgende sein:

http://example.net/svn/foobar

Bash: Summe von Integers berechnen

Ich stand gerade wieder einmal vor dem Problem, dass ich aus einer Logdatei Meldungen nach dem Muster:

        582 media files copied.

extrahieren und davon dann nur die Zahlen zusammenzaehlen wollte. Ein gutes Beispiel um mal ein paar Tools fuer das Arbeiten mit Texten in der Shell vorzustellen.

Als erstes moechte ich alle Zeilen extrahieren. Dafuer nutze ich das Kommando grep:

grep "media files copied." /tmp/logfile

Ich erhalte daraufhin eine Liste mit allen Zeilen, die diesen String enthalten. Als naechstes moechte ich daraus die Nummern extrahieren. Der String beginnt immer mit acht Leerzeichen, und danach steht die Nummer. Hierfuer nutze ich das Kommendo cut, das mir einen String an bestimmten Trennzeichen aufteilt und mir davon die angegebene Spalte ausgibt. Als Trennzeichen eignet sich hier das Leerzeichen, da vor und nach der Nummer eines steht. Da acht Leerzeichen am Anfang sind, brauche ich die neunte Spalte. Dieses erreiche ich mit dem folgenden Code:

grep "media files copied." /tmp/logfile | cut -d " " -f 9

Ich leite also mit der Pipe | die Ausgabe des grep Kommandos weiter zu cut. Das Ergebnis ist eine Liste mit vielen Zahlen, die jede fuer sich in einer eigenen Zeile stehen. Um diese nun mit Hilfe des Kommandos bc zu addieren, muss daraus noch eine Rechenaufgabe werden. Ich greife dafuer auf das Programm paste zurueck. Hiermit kann ich Zeilen zusammenfuehren und dabei den Zeilenumbruch gegen ein von mir vorgegebenes Zeichen ersetzen. In diesem Fall moechte ich, dass jede Zeile nacheineander (seriell, nicht parallel) abgearbeitet wird, und der Zeilenumbruch gegen ein „+“ Zeichen ersetzt wird. Dementsprechend sieht mein Aufruf nun wie folgt aus:

grep "media files copied." /tmp/logfile | cut -d " " -f 9 | paste -sd+

Heraus kommt bei mir gerade das:

32+32+52+32+187+208+22+793+63+632+8+16+40+293+313+48+243+96+32+579+647+768+808+18+48+102+120+258+52+18+52+52+10+52+108+137+512+48+40+48+51+96+582+52+687+101+696+48+48+784+766+776+614+599+804+32+28+779+76+32+86+99+20+34+776+837+44+824+28+803+48

was ich nun nur noch zu bc pipen muss, und schon weiss ich, dass:

grep "media files copied." /tmp/logfile | cut -d " " -f 9 | paste -sd+  | bc

18869 Dateien kopiert wurden.

Vim und ^M

Hatte grad mal wieder das Problem, dass ich in vim eine Textdatei geoeffnet hatte, die voll von ^M war… In der Vim Tips Wiki steht hier was dazu, damit man nicht soviel lesen muss:

:%s/^M/\r/g

Nicht c&p machen davon, sondern das ^M mit Strg+v und Strg+m eingeben ;-)