Mailserver SPF, DKIM, DMARC – Was wie und warum?

Domain-based Authentifizerung für Emails mit SPF, DKIM und DMARC

Vorwort:

Als Admininstrator von Servern stößt man immer wieder auf die Schlagwörter SPF, DKIM, DMARC. Da ich mich nun aufgrund eines aktuellen Projekts ebenfalls mit Email Versand und nicht-als-spam-markiert-werden beschäftigt habe möchte ich hier eine kleine Erklärung und Anleitung zu diesem Thema bereitstellen.

Die Beispielkonfiguration in diesem Artiel verwendet debian Linux mit postfix und opendkim und bind als DNS Server.

Was ist SPF, DKIM, DMARC

Zuerst einmal zur Begriffserklärung:

SPF = Sender Policy Framework – http://en.wikipedia.org/wiki/Sender_Policy_Framework

DKIM = Domain Key Identified Mail – http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail

DMARC = Domain-based Message Authentication, Reporting and Conformance – http://en.wikipedia.org/wiki/DMARC

Wozu?

Alle 3 Methoden helfen, dass die Gegenstelle (Mailempfänger) überprüfen kann ob der Absender (Server) der Email authorisiert ist, Emails unter dieser Domain zu versenden.

Was braucht man dazu und wie funktionierts?

  • opendkim (=milter für Postfix)
  • dns TXT Records

Wird eine Email verschickt hängt der opendkim Dämon (ACHTUNG: nicht mehr dkim-filter verwenden, wird nicht mehr weiterentwickelt) an jede ausgehende Email einen Key an. D.h. er signiert jede Email einer Domain für die er authorisiert ist mit dem hinterlegten Schlüssel.

Dieser Key wird dann vom Empfänger überprüft indem er den entsprechenden DKIM TXT Record (mail._domainkey.domain.tld. IN TXT “v=DKIM1; …”) aus dem DNS abruft und die Signatur prüft.

Zusätzlich kann der Empfänger auch prüfen ob der Versenderserver vom Domaininhaber authorisiert wurde, Emails für diese Domain zu versenden. Dies geschieht indem er den SPF TXT Record (domain.tld. IN TXT “v=spf1 ….”) überprüft. Dort ist z.B. hinterlegt, welcher Mailserver mit welchen Hostnamen und welchen IP Adressen Mails verschicken darf.

Zuletzt kann der Empfänger über den DMARC TXT Record (_dmarc.domain.tld. IN TXT “v=DMARC1; …”) eine Regel einholen, wie er denn mit den Emails verfahren soll, die die Prüfung nicht bestanden haben (z.B. von einem Host geschickt, der im SPF Record nicht erlaubt ist oder die DKIM Signatur nicht überprüft werden konnte).

ran ans Eingemachte – die Konfiguration

Um die zusammengehörigen Konfigurationseinstellungen besser ersichtlich zu machen wurden einzelne zusammengehörige Teile farblich markiert. z.B. die Domain, der Selektor, usw. …

Konfiguration opendkim Daemon

Wie bereits beschrieben sind die Rahmenbedingungen eine funktionierende postfix Installation und voller Zugriff auf die DNS Einträge einer Domain (zum Anlegen von TXT Records).

Installation des opendkim Pakets (debian):

root@shmail:/etc# apt-get install opendkim

Nun muss für den opendkim Daemon und für Postfix noch die Schnittstelle konfiguriert werden, über die beide miteinander kommunizieren. Dies geschieht im /etc/default/opendkim Konfigurationsfile:

root@shmail:/etc/default# cat opendkim
# 20141108 leo.eibler add listener
SOCKET="inet:8891@localhost" # listen on loopback on port 8891

In diesem Beispiel hört der opendkim Daemon auf den localhost Socket Port 8891.

Dazu passend muss nun postfix im Konfigurationsfile /etc/postfix/main.cf konfiguriert werden:

root@shmail:/etc/postfix# cat main.cf
...
# 20141108 leo.eibler add DKIM support
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

Die Konfigurationsdatei des opendkim Pakets selbst liegt in /etc/opendkim.conf . Hier sind nun einige Anpassungen durchzuführen:

root@shmail:/etc# cat opendkim.conf
# Log to syslog
Syslog                  yes
SyslogSuccess           yes
LogWhy                  yes
# Required to use local socket with MTAs that access the socket as a non-privileged user (e.g. Postfix)
UMask                   002

# 20141109 leo.eibler this is a multidomain setup (use different keys for different domains)
# run command for each domain to generate keys:
#   cd /etc/mail
#   opendkim-genkey -r -s mail -d otherdomain.com
#   mv mail.private otherdomain.com.dkim.private
#   mv mail.txt otherdomain.com.dkim.txt
#   chmod ugo+r otherdomain.com.dkim.*
#   /etc/init.d/opendkim restart
# add TXT record to dns from file otherdomain.com.dkim.txt
# append domain to these 2 files:
KeyTable                /etc/mail/DkimKeyTable
SigningTable            refile:/etc/mail/DkimSigningTable

Nach der Konfiguration des opendkim Pakets müssen die entsprechenden Signatur Einträge für die jeweilige Domain erzeugt werden. Hierzu gibt es das opendkim-genkey tool, welches im opendkim Paket mitinstalliert wird:

root@shmail:/etc/mail# opendkim-genkey -r -s mail -d domain.tld

Nach der Ausführung des Kommandos finden sich 2 neue Dateien im Verzeichnis /etc/mail:

  • mail.private = enthält den Schlüssel mit dem die versendete Email vom opendkim/postfix Gespann signiert wird
  • mail.txt = enthält den TXT DNS record mit der Signatur, die vom Empfänger geprüft werden kann

Nun muss opendkim noch mitgeteilt werden, wie es die Keys findet. Der erste Schritt dazu ist die SigningTable Datei. Sie enthält das Mapping von Versender Adresse (FROM: ….@domain.tld) zu Keyfile das für die Signatur verwendet wird:

root@shmail:/etc/mail# cat /etc/mail/DkimSigningTable
# format:
#   $pattern    $keyname
*@domain.tld             domain.tld
*@otherdomain.tld        otherdomain.tld

Der Einfachheit halber wird der keyname gleich wie der Domainname gewählt. Hier könnte man z.B. auch 2 Domains mit dem selben Key signieren, indem der gleiche keyname verwendet wird.

Die zweite Konfigurationsdatei KeyTable enthält mehrere Komponenten:

  • den Verweis auf die Datei mit der Signatur (die Datei mail.private mit opendkim-genkey erstellt wurde):
  • die Domain für die signiert wird
  • den Selektor der vom Empfänger in der DNS Abfrage verwendet wird um die Signatur zu überprüfen
root@shmail:/etc/mail# cat /etc/mail/DkimKeyTable
# format:
#   $keyname    $domain:$selector:$keypath
domain.tld               domain.tld:mail:/etc/mail/domain.tld.dkim.private
otherdomain.tld          otherdomain.tld:mail:/etc/mail/otherdomain.tld.dkim.private

Nach Abschluss der Konfiguration (oder hinzufügen einer Domain) muss der opendkim Daemon neu gestartet werden:

root@shmail:/etc# /etc/init.d/opendkim restart

Häufige Fehler:

  • Die Signaturdatei kann aufgrund der Dateirechte von opendkim nicht gelesen werden (chmod ugo+r … oder chown postfix …)
  • opendkim wurde nicht neugestartet: /etc/init.d/opendkim restart
  • postfix wurde nicht neugestartet: /etc/init.d/postfix restart

Konfiguration DNS Records

Nach der Konfiguration des opendkim Daemons wird nun jede Email von Postfix entsprechend um eine DKIM Signatur ergänzt. Nun fehlen die DNS Einträge, mit denen der Empfänger nun den Versender überprüfen kann.

DNS: Sender Policy Framework (SPF)

Hierzu ist im DNS Zone Record (in diesem Beispiel bind) ein entsprechender TXT Record für die Domain einzurichten:

; TXT records for SPF
domain.tld. IN TXT  (
	 "v=spf1 mx a ip4:10.1.1.40/29 ip4:192.168.0.64/29 "
	 "a:www.domain.tld a:subdomain.domain.tld "
	 "include:mail.hoster.tld"
	 )

Was bedeuten diese Angaben im SPF Record?

  • Der TXT record wird durch die Angabe v=spf1 als SPF Version 1 Record identifiziert
  • mx und a bedeuten, dass der in den MX Records eingetragene Mailserver und die Domain selbst berechtigt ist Emails zu versenden
  • Die beiden ip4:…. Einträge bedeuten, dass Server mit einer IP Adresse in den angegebenen Subnetzen berechtigt sind, Emails für diese Domain zu versenden. Es können durch Hinzufügen mehrerer ip4 Abschnitte mehrere IP Nutze angegeben werden (in diesem Beispiel 2). Hier müssen z.B. die IP Adressen der Mailrelays des Hosters eingetragen werden
  • Die a:<subdomain>.domain.tld Einträge erlauben das Versenden von Mails von den angegebenen Subdomains. Auch hier sind mehrere Einträge für mehrere Subdomains erlaubt
  • Die include:<andere Domain> Einträge fügen weitere Domains bzw. Hosts hinzu, denen es erlaubt ist, Emails zu versenden. Hier wird z.B. das Mailrelay des Hosters eingetragen. Auch hier sind mehrere Einträge für mehrere andere Domains erlaubt

Häufige Fehler:

  • Der Punkt nach dem Domainnamen fehlt: domain<PUNKT>tld<PUNKT> IN TXT ”….”
  • Der TXT Record ist zu lange. Hier in diesem Beispiel wurde der TXT Record auf mehrere Zeilen aufgetrennt. Die Syntax hierfür lautet: Klammer auf ( danach in Anführungszeichen “erster Teil<Leerzeichen>” danach nächste Zeile in Anführungszeichen “zweiter Teil” usw. und abschließend Klammer zu ). Wichtig hierbei: Die Leerzeichen innerhalb der einzelnen in Anführungszeichen eingeschlossenen Abschnitte nicht vergessen: “erster Teil” “zweiter Teil” wird sonst zu “erster Teilzweiter Teil” zusammengesetzt.
  • Die Serial Number des Zone Records wurde nicht erhöht
  • Die Ablaufzeit des Zone Records ist sehr hoch gesetzt und die anderen Server haben die Änderungen noch nicht mitbekommen

DNS: Domain Key Identified Mail (DKIM)

Für das DKIM Signatur Verfahren sind ebenfalls im DNS Zone Record (in diesem Beispiel bind) ein entsprechender TXT Record für die Domain einzurichten:

mail._domainkey.domain.tld. IN TXT  (
	 "v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvkDET02OqKcvgkpSxRvGMVzqwj5fxNFcuLWhLCcMsdx7hxlquRppBjbirvEV0HgRHS/za+KKp45edd4qBeChASEbJJ2NpNGIyL+Jy0jmpCK1E5AZKopjSLnSMo78lkaZDj/t5XRqj0qhnldUgtOGj6M8PHvN7AH9UBpXxhXAe1QIDAQAB"
	 )

Nun ist der Selektormail” wichtig, der in der opendkim Konfiguration angegeben wurde:

  • siehe opendkim-genkey -r -s mail -d domain.tld Aufruf mit -s mail = Selektor “mail
  • siehe Konfigurationsdatei KeyTable mit domain.tld domain.tld:mail:/etc/mail/domain.tld.dkim.private = Selektor :mail:

Der TXT Record wird also mit mail._domainkey.domain.tld. angelegt.

Was bedeuten diese Angaben im DKIM Record?

  • Der TXT record wird durch die Angabe v=DKIM1 als DKIM Version 1 Record identifiziert
  • Das Verschlüsselungsverfahren RSA wird mit k=rsa festgelegt
  • Der Schlüssel zum Überprüfen wird mit p=<key> festgelegt. Dies ist der Schlüssel der durch opendkim-genkey in der mail.txt Datei erzeugt wurde

Häufige Fehler:

  • Der Punkt nach dem Domainnamen fehlt: mail<PUNKT>_domainkey<PUNKT>domain<PUNKT>tld<PUNKT> IN TXT ”….”
  • Der Selektor (hier im Beispiel mail) ist falsch bzw. stimmt nicht mit der opendkim Konfiguration überein
  • Serial Number oder Caching des Zone Records

DNS: Domain-based Message Authentication, Reporting and Conformance (DMARC) Richtlinie

Die DMARC Richtlinie sagt dem Empfänger, wie er denn mit einer Email die nicht die Prüfungen für SPF und/oder DKIM bestanden hat umzugehen hat.

Die DMARC Richtlinie wird ebenfalls im DNS Zone Record (in diesem Beispiel bind) über einen entsprechenden TXT Record für die Domain veröffentlicht:

_dmarc.domain.tld. IN TXT “v=DMARC1; p=quarantine; rua=mailto:postmaster@domain.tld”

Der TXT Record wird also mit _dmarc.domain.tld. angelegt.

Was bedeuten diese Angaben in der DMARC Richtlinie?

  • Der TXT record wird durch die Angabe v=DMARC1 als DMARC Version 1 Record identifiziert
  • Die Angabe p=quarantine bedeutet, dass eine Email die nicht die Prüfungen besteht entsprechend markiert (z.B. als Spam) werden soll. Weitere Alternativen hierzu wären p=none – dies wird als TEST Mode bezeichnet (der Empfänger prüft zwar ignoriert aber das Ergebnis und behandelt die Domain wie wenn keine SPF und DKIM Records existieren würden). Die härteste Variante ist mit p=reject anzugeben – Emails werden bei fehlerhafter Überprüfung abgewiesen
  • An die im optionalen Parameter rua=<Email-Adresse> angegebene Email Adresse wird täglich ein XML Report versendet mit einer Zusammenfassung über die fehlerhaften Emails die beim Empfänger eingelangt sind

Weitere Parameter und Angaben finden sich auf der DMARC Webseite: http://www.dmarc.org

Häufige Fehler:

  • Der Punkt nach dem Domainnamen fehlt: _dmarc<PUNKT>domain<PUNKT>tld<PUNKT> IN TXT ”….”
  • Es ist der Test Modus aktiv p=none
  • Serial Number oder Caching des Zone Records

Testen der Einrichtung

Testen der DNS Konfiguration

Zuerst kann die DNS Einrichtung der TXT Records z.B. mit dig oder nslookup überprüft werden (alle Ausgaben gekürzt).

Überprüfen des DNS Servers ns1.hoster.tld auf dem die TXT Records für die Domain angelegt wurden – SPF:

root@soyuz:~# dig @ns1.hoster.tld. TXT domain.tld
; <<>> DiG 9.7.3 <<>> @ns1.hoster.tld. TXT domain.tld
domain.tld. 21600 IN TXT  "v=spf1 mx a ip4:10.1.1.40/29 ip4:192.168.0.64/29 a:www.domain.tld a:subdomain.domain.tld include:mail.hoster.tld"

Man sieht hier schön, dass die einzelnen Teile in Anführungszeichen zusammengefügt wurden und als ein ganzer Block ausgegeben werden. Hier kann man nun kontrollieren ob man z.B. ein Leerzeichen in einem Block vergessen hat.

Überprüfen des DNS Servers ns1.hoster.tld auf dem die TXT Records für die Domain angelegt wurden – DKIM:

root@soyuz:~# dig @ns1.hoster.tld. TXT mail._domainkey.domain.tld
; <<>> DiG 9.7.3 <<>> @ns1.hoster.tld. TXT mail._domainkey.domain.tld
mail._domainkey.domain.tld. 21600 IN TXT  "v=DKIM1\; g=*\; k=rsa\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvkDET02OqKcvgkpSxRvGMVzqwj5fxNFcuLWhLCcMsdx7hxlquRppBjbirvEV0HgRHS/za+KKp45edd4qBeChASEbJJ2NpNGIyL+Jy0jmpCK1E5AZKopjSLnSMo78lkaZDj/t5XRqj0qhnldUgtOGj6M8PHvN7AH9UBpXxhXAe1QIDAQAB"

Überprüfen des DNS Servers ns1.hoster.tld auf dem die TXT Records für die Domain angelegt wurden – DMARC:

root@soyuz:~# dig @ns1.hoster.tld. TXT _dmarc.domain.tld
; <<>> DiG 9.7.3 <<>> @ns1.hoster.tld. TXT _dmarc.domain.tld
_dmarc.domain.tld. 21600  IN      TXT     "v=DMARC1\; p=quarantine\; rua=mailto:postmaster@domain.tld"

Testen der Mail Konfiguration

Verschicken einer Email von der jeweiligen Domain an einen Test Service wie z.B. check-auth@verifier.port25.com

root@test:~# echo "Dies ist ein Test" | mail -s "test email" check-auth@verifier.port25.com -- -f postmaster@domain.tld

Nun sollte auf der Absender Email Adresse postmaster@domain.tld eine Antwort eintreffen die hoffentlich so aussieht:

...
==========================================================
Summary of Results
==========================================================
SPF check:          pass
DomainKeys check:   neutral
DKIM check:         pass
DKIM check:         pass
Sender-ID check:    pass
SpamAssassin check: ham
...

Falls bei SPF, DKIM und Sender-ID jeweils pass steht funktioniert die Konfiguration.

Gratulation! gmail signiert durch domain.tld
Gratulation! gmail signiert durch domain.tld

Eine Prüfung ist auch einfach mittels gmail möglich.

Hat alles geklappt zeigt gmail Signiert durch: domain.tld

 

 

Gratulation!

Über den Autor

Ing. Leo Eibler ist hauptberuflich im Bereich Beratung und IT Service Management tätig. Neben seiner beruflichen Tätigkeit entwickelt er Webapplikationen und kümmert sich auf freiwilliger Basis um den Betrieb von diversen Servern.

http://www.eibler.at/

Ähnliche Artikel:

Tomcat + Apache2 auf Debian

Wär doch toll wenn man die Anwendungen die auf dem Tomcat laufen würden auch über den normalen 80er Zugriff erreichen könnte. Apache mod_jk machts möglich!

Aus Zwei mach Eins

Da ich gerade meinen Heimserver um diverse Entwickler Tools aufstocken möchte (Jenkins, Sonar, Nexus) musste erstmal ein Servlet-Container her: Tomcat
Port 80 ist bereits freigegeben und eigentlich nervt mich das Portgetippe (eh schon wissen: localhost:8080) beim URL Aufruf ziemlich. Wär doch toll wenn man die Anwendungen die auf dem Tomcat laufen würden auch über den normalen 80er Zugriff erreichen könnte, oder?

Naja, dann ran ans Eingemachte!

Installation Tomcat

Java

So noch nicht geschehen sollte sinnvollerweise eine Java Installation am Server vorhanden sein

# apt-get install openjdk-6-jre

Wer auf dem Server auch Programme compiliern will besorgt sich ein jdk. Für die Installatin von Java 7 verweise ich auf einen ausgezeichneten Blog Beitrag von SysadminsLife

Download und Installation

Auf der Tomcat Seite die gewünschte Version (im Falle des Tutorials die neueste 7.0) mit wget herunterladen und entpacken

# tar xvfz apache-tomcat-7.0.35.tar.gz

danach an eine passende Stelle verschieben /opt/tomcat

# mv apache-tomcat-7.0.35 /opt/tomcat

Zum Abschluss noch die Scripts ausführbar machen

# chmod +x /opt/tomcat/bin/*.sh

Tomcat User und Gruppe

# groupadd tomcat
# useradd -g tomcat -d /opt/tomcat tomcat
# usermod -G www-data tomcat
# chown tomcat:tomcat /opt/tomcat -R

Tomcat Startup Script

Unter /etc/init.d/tomcat wird das Tomcat 7 Script von collinpeters abgespeichert (Oh ja, Github rulez! Und gist erst recht – Danke für das schöne Script!)

Natürlich muss das Script noch ausführbar gemacht werden und es soll automatisch starten

# chmod +x /etc/init.d/tomcat
# update-rc.d tomcat defaults

Tomcat Server User

Tomcat will auch abgesichert sein, zumindest ein bisschen. Daher legen wir einen Benutzer für die Admin und Manager Webapps an. Unter /opts/tomcat/conf/tomcat-users.xml ist folgendes zu ergänzen

<tomcat-users>
    <role rolename="manager" />
    <role rolename="manager-gui" />
    <role rolename="admin"/>
    <role rolename="admin-gui"   />
    <user username="USER" password="PASSWORT"
     roles="admin,admin-gui,manager,manager-gui" />
</tomcat-users>

Bitte USER und PASSWORT durch eure Werte ersetzen.

Start und Test

Es wär alles für die Katz würden wir es nicht auch testen. Dafür starten wir das Service

# /etc/init.d/tomcat start

Nun sollte Tomcat unter http://<server-ip>:8080 erreichbar sein.

Installation mod_jk Apache connector

apt-get

Wie immer, als erstes ist das Package zu installieren:

# apt-get install libapache2-mod-jk

Dieses Apache Modul dient als Brücke zwischen dem Webserver und Tomcat

mod_jk Konfiguration

Mit ein paar Zeilen unter /etc/apache2/conf.d/jk.conf wird mod_jk konfiguriert

<ifmodule mod_jk.c>
    JkWorkersFile /etc/apache2/workers.properties
    JkLogFile /var/log/apache2/mod_jk.log
    JkLogLevel error
</ifmodule>

mod_jk Worker

Apache benötigt nun noch eine Konfiguration in der festgehalten wird wie er einen Request auf Tomcat umleitet

Unter /etc/apache2/workers.properties legen wir daher folgende Konfiguratino ab

workers.tomcat_home=/opt/tomcat
workers.java_home=/usr/lib/jvm/java-6-openjdk
ps=/
worker.list=default
worker.default.port=8009
worker.default.host=localhost
worker.default.type=ajp13
worker.default.lbfactor=1

sites-available

Nun muss Apache nur noch erfahren welche Requests er an Tomcat weiterleiten soll. Dazu fügen wir in /etc/apache2/sites-available/default JkMount Zuordnungen ein. Im Falle der Tomcat Manager Applikation wären das folgende Zeilen 8 und 9

<VirtualHost *>
ServerAdmin root@localhost
ServerAlias homeserver

DocumentRoot /var/www/
# weitere Konfiguration

JkMount /manager default
JkMount /manager/* default

</VirtualHost>

Test

Nun muss Apache natürlich neu gestartet werden:

# /etc/init.d/tomcat restart

Das wars, nun sollte unter http://<server-ip>/manager die erste Weiterleitung auf den Tomcat sichtbar sein!

Viel Spaß damit!

Ähnliche Artikel:

Mit Bash prüfen ob das eigene Script gerade läuft

Die Problemstellung

Ein Script soll alle x Minuten laufen und eine bestimmte Tätigkeit auf dem Server ausführen.

Nun kann es vorkommen, dass das Script aber länger braucht als die Zeitspanne bis zum nächsten Aufruf desselben Scripts (z.B. Kopier und Backup Jobs, Mails abholen, …)

Natürlich sollte so ein Script dann nicht ein 2tes Mal gestartet werden sondern die Ausführung übersprungen werden. Zu diesem Zweck möchte ich hier ein kleines Bash Script zeigen, das genau diesen Zweck erfüllt.

Die Lösung

#!/bin/bash
#
# testpid.sh - demo script to show how to check if a script
# with the same name is currently running
#
# by Leo Eibler
# resources:
#    http://www.eibler.at
#    http://leo.sprossenwanne.at
#    http://www.nullpointer.at
#

# PID - pid of the current script
PID=$$
# SCRIPTNAME - current name of the script without directory prefix
SCRIPTNAME=`basename $0`
# PIDFILE - where to write the current pid
PIDFILE=/tmp/$SCRIPTNAME.pid

# ENDEXECUTION - if 1 then stop script, if 0 everything is ok and continue
ENDEXECUTION=0

if [ -f "$PIDFILE" ]
then
    RUNNINGPID=`cat "$PIDFILE"`
    echo "got pid from $RUNNINGPID from pidfile '$PIDFILE'"
    PROGRAMPID=`ps -e | grep "$SCRIPTNAME" | grep -v grep | awk '{print $1;}'`
    for PIDEL in $PROGRAMPID
    do
        echo "testing pid of running scripts '$PIDEL' == '$RUNNINGPID' from pidfile"
        if [ "$PIDEL" == "$RUNNINGPID" ]
        then
            echo "found PID $RUNNINGPID current running - end execution"
            ENDEXECUTION=1
            break
        fi
    done
fi

if [ "$ENDEXECUTION" == "1" ]
then
    echo "Current script '$SCRIPTNAME' already running (pid $RUNNINGPID) - end execution"
    exit 1
fi
# writing PID to pidfile
echo $PID > $PIDFILE

#
# ---- START ----
#

echo "do your stuff here ..."
sleep 5
echo "... end script"

#
# ---- END ----
#

# delete pidfile
rm $PIDFILE
exit 0

Die Erklärung

Zuerst holt sich das Script den eigenen Namen mit basename $0 ($0 würde ebenfalls den Pfad des Scriptaufrufs enthalten aber hier würde der spätere Aufruf von ps bzw. das automatische Erstellen und Auslesen des passenden pid-Files scheitern).

Mit dem Namen des Scripts wird dann versucht ein pid-File (welches die Process-ID des aktuell laufenden Scripts enthält) auszulesen. Der Pfad des pid-Files kann beliebig gewählt werden, jedoch muss das Script natürlich Schreibrechte auf die Datei besitzen.

Falls kein pid-File existiert kann das Script davon ausgehen, dass es derzeit nicht bereits läuft und seine eigentliche Arbeit aufnehmen.

Falls jedoch ein pid-File vorhanden ist, wird dieses ausgelesen und mit allen derzeit laufenden Process-IDs von Prozessen mit dem gleichen Namen wie das Script verglichen.

Wird hierbei eine Übereinstimmung gefunden, dann läuft das Script bereits und durch Setzen der Variable $ENDEXECUTION auf 1 wird der Abbruch signalisiert.

Dieser Vergleich mit den Process-IDs von Prozessen die bereits laufen ist deswegen wichtig, da es ja sein könnte, dass das Script beim vorherigen Aufruf zwar ein pid-File angelegt hat, aber danach abgebrochen wurde (z.B. manuell durch den Benutzer) und das pid-File dadurch nicht gelöscht wurde.

Ist die Überprüfung auf eine laufende Instanz negativ, muss zuerst das pid-File angelegt werden (Die Variable $$ enthält die pid des aktuellen Prozesses).

Nach Beendigung der Arbeit sollte danach das pid-File wieder gelöscht werden um einen sauberen Abschluss zu bilden.

Das Script als Download gibts hier.

 

Ähnliche Artikel:

Dateien zählen unter Linux

Otto Normal hat mit Datein Zählen unter Windows sicher keine Probleme und die meisten Linuxuser unter dem Betriebssystem ihrer Wahl wohl auch nicht. Will aber Otto mal in Linux reinschnuppern und dort Dateien zählen, stellt ihn das als Laien vor eine respektable Herausforderung.

Otto Normal hat damit unter Windows sicher keine Probleme und die meisten Linuxuser unter dem Betriebssystem ihrer Wahl wohl auch nicht. Will aber Otto mal in Linux reinschnuppern und dort Dateien zählen, stellt ihn das als Laien vor eine respektable Herausforderung.

Um sich den Inhalt eines Verzeichnisses aufzurufen ist ihm wahrschienlich schon der Befehl

ls

bekannt. ls steht für “list” Doch liefert dieser Befehl lediglich eine Auflistung des Inhalts des gegenwärtigen Verzeichnisses. Daher muss diese Ausgabe noch ausgewertet werden. Hierfür setzen wir Pipes | ein mit denen man mehrere Kommandos miteinander verbinden kann. Hierbei wird jeweils die Ausgabe des vorhergehenden Befehls als Eingabe für den nächsten Befehl herangezogen.

ls –1 | wc –l

wir haben hierbei den ls Befehl um den Parameter –1 (Zahl Eins) erweitert der für eine lange Listenform steht. Es wird somit jedes Element in einer extra Zeile angeführt. Die Ausgabe davon wird per Pipe an den wc Befehl weitergeleitet. wc steht in diesem Fall für Word Count. Erneut über einen Parameter –l (kleines L) weisen wir wc darauf hin, dass es die Zeilen zählen soll, die es übergeben bekommt.

Achtung! Wurde statt der 1 ein kleines L als Parameter an ls übergeben ist die Ausgabe um eins größer als die Anzahl der Elemente. Dies liegt daran, dass dabei noch eine weitere Zeile Output erzeugt wird, die keine Datei wiederspiegelt.

ls –l <targetdir> | wc –l

Wollen wir nicht direkt das Ergebnis aus dem Verzeichnis in dem wir uns befinden, können wir das Zielverzeichnis am ls Befehl anhängen.

Fürs erste kann man damit zufrieden sein, doch bei genauerer Betrachtung stößt man dabei rasch an die Grenzen des Befehls. Man zählt nämlich symbolische Links und Verzeichnisse und Dateien gleichermaßen.

Wir tauschen nun also den list Befehl gegen einen spezialisierteren Befehl  aus: find

find <targetdir> –maxdepth 1 –type f | wc –l

Mit -type f schränkt man die Auflistung der Ergebnisse auf Datein (files) ein. Dies könnte man z.B. auch auf Verzeichnisse (directorys) einschränken: –type d

Achtung, bei der Auflistung der Verzeichnisse wird das gegenwärtige Verzeichnis . mitgezählt, vom Gesamtergebnis also wieder eins abziehen.

Von Haus aus würde der find Befehl alle Unterverzeichnisse absuchen. Mittels –maxdepth <zahl> kann die Tiefe die er dabei erreicht steuern. Die 1 aus dem Beispiel oben steht hierbei nur für das Wurzelverzeichnis. Möchte man lediglich eine Verzeichnisebene tiefer wäre –maxdepth 2 der passende Parameter.

Will man nun auch wieder die symbolischen Links in seinem Suchergebnis dabei haben muss man den find Befehl noch um den –follow Parameter erweitern

find <targetdir> –maxdepth 1 –type f –follow | wc –l

Möchte man nun noch auf Dateiendungen oder anderen Teilen des Dateinamens einschränken gilt es noch den -name ‚*.txt‘ Parameter zu erwähnen. Zwischen den Anführungszeichen wir der Suchbegriff angeführt, * und ? gelten dabei als die üblichen Wildcards.

find <targetdir> -maxdepth 1 -type f -follow -name '*.t?t' | wc -l

Happy counting!

PS: Rekursives suchen wäre mit dem ls Befehl mittels –R Parameter möglich

Ähnliche Artikel:

mail.log – versendete Mails erfassen

Ein Mailserver bedarf eines wachsamen Auges! Um Probleme wie eine Spamschleuder zu entdecken helfen schon ein paar simple Linux Befehle zum filtern von mail.log

Bei der Kontrolle der Aktivitäten eines Mailservers bleibt einem oft nichts anderes über als sich durch die Logfiles zu wälzen. um einen Schnellen blick auf alle Email zu erhalten, die der Server zuletzt verschickt hat, kann man die mail.log Datei folgendermaßen filtern:

cat /var/log/mail.log | grep postfix | grep "to=<" | grep "status=sent"

Damit erhält Informationen zu allen versandten E-Mails: hier eine Beispielausgabe:

Mar  7 16:19:57 mailserver postfix/pipe[17596]: 753C62F9D: to=john@example.org, orig_to=<john@example.org>, relay=dovecot, delay=0.54, delays=0.01/0/0/0.53, dsn=2.0.0, status=sent (delivered via dovecot service)

Anhand der ID (In diesem Fall 753C62F9D lassen sich dann noch detailiertere Informationen zu den jeweiligen Emails auslesen, wie zB den Sender usw.

Für eine schnelle händische Kontrolle zwischendurch absolut ausreichend.

Wer schönere Ausgaben haben möchte splittet die Ausgabe noch etwas auf und lässt sich nur teile ausgeben:

cat /var/log/mail.log | grep postfix | grep "to=<" | grep "status=sent" | cut -d':' -f4-5 | cut -d',' –f1

Ergebnis:

753C62F9D: to=<john@example.org>

Bessere Logauswertungen und Zusammenfassungen bekommt man mit Tools wie zB pflogsumm, awstats oder mailgraph die in den Paket-Repositories der Distribution eurer Wahl auch vorhanden sein sollten.

Mit täglich gemailten Statistiken über pflogsumm habt ihr euren Server im Auge falls Unregelmäßigkeiten auftreten, Wochen- Monats und später mal Jahresstatistiken stellen euch die graphischen Tools awstats oder mailgraph zur Verfügung.

Bei soviel praktischer Hilfe ist das wachsame Auge über dem Mailserver ein leichtes :)

Ähnliche Artikel: