Schlagwort-Archive: tipps

NGINX verweigert Neustart – [emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use)

In diesem Artikel möchte ich einige Informationen zur NGINX-Fehlermeldung „[emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use)“ wiedergeben.

Als ich heute Morgen die E-Mail-Reports meiner Server durchgesehen habe, fiel mir die Meldung ins Auge, dass auf einem meiner Server die NGINX-Konfiguration nicht erneut eingelesen werden konnte. Auch der Versuch eines manuellen Neustarts wurde mit folgender Meldung quittiert:

# sudo service nginx restart
* Restarting nginx nginx [fail]

Konfiguration überprüfen

Die obige Meldung gibt noch keinerlei Hinweise auf die Ursache des Fehlers. Mit dem folgenden Kommando lässt sich die Konfiguration des NGINX überprüfen und der Fehler etwas eingrenzen:

# sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] listen() to 0.0.0.0:80, backlog 511 failed (98: Address already in use)
nginx: configuration file /etc/nginx/nginx.conf test failed

Die Fehlermeldung sagt aus, dass der NGINX-Prozess nicht erneut an den Port 80 gebunden werden kann, da dieser bereits verwendet wird. Für mich noch immer etwas verwirrend, da NGINX ja noch läuft und selbstverständlich auf Port 80 lauscht. Weshalb dadurch plötzlich kein Neustart mehr möglich ist, erschließt sich mir noch nicht.

Eine Lösung

Bei der Internetrecherche nach einer Lösung, bin ich auf einen englischsprachigen Troubleshootingguide gestoßen, welcher empfiehlt, alle Prozesse, die auf Port 80 lauschen, mit dem folgenden Kommando zu beenden:

sudo fuser -k 80/tcp

Anschließend konnte ich den NGINX wie gewohnt neu starten (restart) oder die Konfiguration neu einlesen (reload). Das Problem scheint damit erstmal behoben zu sein.

Kurztipp: nginx_modsite

In diesem Post möchte ich ganz kurz das Skript nginx_modsite vorstellen.

Dieses ermöglicht die einfache De-/Aktivierung von Nginx-Konfigurationsdateien in den Standard-Verzeichnissen /etc/nginx/sites-available und /etc/nginx/sites-enabled.

Das Skript wurde ursprünglich 2010 von Michael Lustfield erstellt. Es ist u.a. in meinem GitHub-Repository1 zu finden.

Zur einfachen Verwendung kopiert man das Skript in das Verzeichnis /usr/local/sbin. Ruft man es mit den Argumenten -h bzw. --help auf, erhält man eine Übersicht der verfügbaren Optionen:

sudo nginx_modsite -h
Usage: nginx_modsite [options]
Options:
<-e|--enable> Enable site
<-d|--disable> Disable site
<-l|--list> List sites
<-h|--help> Display help

If is left out a selection of options will be presented.
It is assumed you are using the default sites-enabled and
sites-disabled located at /etc/nginx.

Somit müssen die Links in /etc/nginx/sites-enabled nicht mehr per Hand erstellt werden. Alles in allem ein sehr schönes Skript, welches ich nicht mehr missen möchte.

Ansible – Was ich am Ad-hoc-Modus schätze

Schon seit einiger Zeit hilft mir Ansible1 fast täglich dabei, meine Arbeit leichter zu gestalten. Heute möchte ich euch ganz kurz erzählen, was ich am Ad-hoc-Modus schätze.

Der Ad-hoc-Modus bietet die Möglichkeit, einfache Kommandos parallel auf einer Gruppe von Nodes ausführen zu lassen, ohne zuvor ein Playbook erstellen zu müssen. Ein Ad-hoc-Befehl besitzt z.B. den folgenden Aufbau:

ansible [-m module_name] [-a args] [options]

Ein einfaches Beispiel aus der Ansible-Dokumentation2 soll die Anwendung verdeutlichen:

# ansible all -m ping -i staging --limit=e-stage
host01.example.com | SUCCESS => {
"changed": false,
"ping": "pong"
}
host02.example.com | SUCCESS => {
"changed": false,
"ping": "pong"
}
host03.example.com | SUCCESS => {
"changed": false,
"ping": "pong"
}

Das Schlüsselwort all gibt an, dass das Kommando auf allen Nodes ausgeführt werden soll, welche in der Inventar-Datei enthalten sind. Mit -m ping wird das zu verwendende Ansible-Modul spezifiziert. Da das verwendete Modul keine weiteren Argumente besitzt, findet -a in diesem Beispiel keine Anwendung. Mit der Option -i kann die zu verwendende Inventar-Datei angegeben werden. Lässt man diese Option weg, wird die Standard-Inventar-Datei /etc/ansible/hosts verwendet. Mit der Option --limit=e-stage wird die Ausführung noch weiter eingeschränkt. So wird in diesem Fall das Modul ping nur auf den Nodes der Gruppe e-stage ausgeführt. Das in diesem Beispiel verwendete Inventar besitzt den folgenden Aufbau:

[e-stage]
host01.example.com
host02.example.com
host03.example.com
host06.example.com
host07.example.com

[i-stage]
host04.example.com

[p-stage]
host05.example.com

Verknüpfung mit weiteren Kommandos

Selbstverständlich lassen sich Ansible-Ad-hoc-Kommandos auf der Kommandozeile auch weiter verknüpfen. Dies soll an zwei kleinen Beispielen verdeutlicht werden.

Status eines Dienstes prüfen

In diesem ersten Beispiel soll der Status des Dienstes chronyd überprüft werden, ohne den aktuellen Status zu ändern. Dabei soll das Kommando systemctl status chronyd.service via Ansible parallel auf den Nodes ausgeführt werden.

Zuvor habe ich mir auf einem Node angesehen, wie die Ansible-Ausgabe in Abhängigkeit vom Dienststatus aussieht (Ausgabe gekürzt):

# Der Dienst auf dem Node ist gestartet
root@ansible-control-machine>ansible all -m command -a'/usr/bin/systemctl status chronyd.service' -i staging -l host01.example.com
host01.example.com | SUCCESS | rc=0 >>
* chronyd.service - NTP client/server
Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2016-12-15 14:52:02 CET; 19h ago

# Der Dienst auf dem Node ist gestoppt
root@ansible-control-machine>ansible all -m command -a’/usr/bin/systemctl status chronyd.service‘ -i staging -l host01.example.com
host01.example.com | FAILED | rc=3 >>
* chronyd.service – NTP client/server
Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Fri 2016-12-16 10:04:34 CET; 4s ago

# Das Paket, welches den Dienst enthaelt ist nicht installiert
root@ansible-control-machine>ansible all -m command -a’/usr/bin/systemctl status chronyd.service‘ -i staging -l host01.example.com
host01.example.com | FAILED | rc=4 >>
Unit chronyd.service could not be found.

Anhand der Ausgaben ist zu erkennen, dass Ansible den Task als „| SUCCESS |“ markiert, wenn der Dienst läuft und als „| FAILED |“, wenn der Dienst gestoppt bzw. gar nicht installiert ist. Durch Verknüpfung des Kommandos mit grep kann man sich nun schnell einen Überblick über den Dienststatus auf seinen Rechnern verschaffen:

root@ansible-control-machine> ansible all -m command -a'/usr/bin/systemctl status chronyd.service' -i staging --limit=e-stage | grep '| SUCCESS |\|| FAILED |'
host01.example.com | SUCCESS | rc=0 >>
host02.example.com | SUCCESS | rc=0 >>
host03.example.com | FAILED | rc=3 >>
host06.example.com | SUCCESS | rc=0 >>
host07.example.com | SUCCESS | rc=0 >>

Anhand der Ausgabe ist leicht zu erkennen, dass der Dienst chronyd auf host03 nicht läuft. Anhand des Return-Codes rc=3 lässt sich weiterhin erkennen, dass das notwendige Paket offensichtlich installiert ist, der Dienst jedoch nicht gestartet wurde. Dies kann nun jedoch schnell durch folgenden Befehl korrigiert werden (Ausgabe gekürzt):

root@ansible-control-machine>ansible host03.example.com -m systemd -a'name=chronyd state=started' -i staging
host03.example.com | SUCCESS => {
"changed": true,
"name": "chronyd",
"state": "started",
"status": {...}
}

Eine erneute Ausführung des ersten Kommandos bestätigt, dass der Dienst nun auch auf dem Node host03 ausgeführt wird.

root@ansible-control-machine> ansible all -m command -a'/usr/bin/systemctl status chronyd.service' -i staging --limit=e-stage | grep '| SUCCESS |\|| FAILED |'
host01.example.com | SUCCESS | rc=0 >>
host02.example.com | SUCCESS | rc=0 >>
host03.example.com | SUCCESS | rc=0 >>
host06.example.com | SUCCESS | rc=0 >>
host07.example.com | SUCCESS | rc=0 >>

Paketversion überprüfen

In diesem Beispiel möchte ich die installierte Version des Pakets tzdata abfragen. Dies geschieht auf einem einzelnen Host mit dem Kommando rpm -qi :

# rpm -qi tzdata
Name : tzdata
Version : 2016i
Release : 1.el7
Architecture: noarch
Install Date: Wed Nov 9 08:47:03 2016
Group : System Environment/Base
Size : 1783642
License : Public Domain
Signature : RSA/SHA256, Fri Nov 4 17:21:59 2016, Key ID 199e2f91fd431d51
Source RPM : tzdata-2016i-1.el7.src.rpm
Build Date : Thu Nov 3 12:46:39 2016
Build Host : ppc-045.build.eng.bos.redhat.com
Relocations : (not relocatable)
Packager : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
Vendor : Red Hat, Inc.
URL : https://www.iana.org/time-zones
Summary : Timezone data
Description :
This package contains data files with rules for various timezones around
the world.

Mich interessiert lediglich die zweite Zeile, welche die Version des Pakets enthält. Die frage ich nun wie folgt ab:

root@ansible-control-machine> ansible all -m command -a'/usr/bin/rpm -qi tzdata' -i staging --limit=e-stage | grep 'SUCCESS\|Version'
host01.example.com | SUCCESS | rc=0 >>
Version : 2016f
host02.example.com | SUCCESS | rc=0 >>
Version : 2016g
host03.example.com | SUCCESS | rc=0 >>
Version : 2016i
host06.example.com | SUCCESS | rc=0 >>
Version : 2016i
host07.example.com | SUCCESS | rc=0 >>
Version : 2016i

Ohne Ansible hätte ich diese Aufgaben entweder mit Iteration in einem kurzen Shell-Skript lösen müssen, oder zuerst ein Kochbuch, Manifest, etc. schreiben, welches dann anschließend ausgeführt werden kann. So wurde mir hingegen einiges an Zeit gespart, die ich für andere Dinge verwenden konnte.

Quellen und weiterführende Links

RHEL/CentOS 7 – Root Passwort zurücksetzen

In diesem Tutorial wird beschrieben, wie das root-Passwort bei RHEL/CentOS 7 mit Bordmitteln zurückgesetzt werden kann. Mit Bordmitteln bedeutet, dass hierbei keine externen Bootmedien verwendet werden.

Aufgepasst! Macht man bei der Ausführung der folgenden Prozedur Fehler, können diese dazu führen, dass man jeglichen Zugang zu einem System verliert. Möchte man die Vorgehensweise üben, empfehle ich, dies ausschließlich auf Testsystemen zu tun.

Die Ausgangssituation

Das root-Passwort eines RHEL/CentOS 7 Servers ist unbekannt und muss zurückgesetzt werden. Es ist keine geöffnete root-Shell vorhanden und es ist kein Benutzer am System angemeldet, welcher über vollständige sudo-Berechtigungen verfügt.

Das Passwort soll ohne Einsatz externer Bootmedien zurückgesetzt werden.

Vorgehensweise

Schritt 1: Es wird ein Neustart des Systems durchgeführt. Sobald das Grub2-Boot-Menü erscheint, wird der Bootloader-Countdown durch Drücken einer beliebigen Taste unterbrochen.

Nun wählt man den gewünschten Eintrag (dies ist meist der erste in der Liste) aus und wechselt mit Drücken der Taste ‚e‘ in den Bearbeitungsmodus (siehe Abbildung 1).

abb1-grub2-menu

Abbildung 1: Grub2-Bootmenü

Schritt 2: Der Cursor wird zur Kernel-Kommandozeile bewegt. Diese beginnt üblicherweise mit dem Wort linux16. Hier wird, wie in Abbildung 2, ein „rd.break“ an das Ende der Zeile angefügt.

edit-kernel-command-line

Abbildung 2: Bearbeitete Startparameter für den Kernel

Die Bearbeitung wird durch Drücken der Tastenkombination Strg+x beendet und der Bootvorgang fortgesetzt. Der Bootvorgang wird an der Stelle angehalten, an der man sich in der Initial-Ram-Disk befindet, direkt bevor das eigentliche System gestartet wird. An dieser Stelle findet man den Inhalt des eigentlichen /-Dateisystems unterhalb von /sysroot.

Schritt 3: Nach Schritt 2 befindet man sich nun in einer root-Shell. Da das eigentliche Dateisystem unterhalb von /sysroot schreibgeschützt eingehängt wurde, muss dieses zunächst remountet werden. Dies geschieht mit dem folgenden Kommando (vgl. Abbildung 3):

switch_root:/# mount -oremount,rw /sysroot
remount-sysroot

Abbildung 3: Remount /sysroot

Schritt 4: In diesem Schritt wechselt man mittels chroot1 in das /sysroot-Verzeichnis und setzt ein neues Passwort für den Benutzer root.

switch_root:/# chroot /sysroot
sh-4.2# passwd root
Changing password for user root.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

Wichtig: SELinux2 ist zu diesem Zeitpunkt noch nicht aktiv. Dies bedeutet, dass alle neuen Dateien ohne einen entsprechenden SELinux-Kontext erstellt werden. Das Programm passwd arbeitet so, dass es erst eine neue Datei erstellt und mit dieser anschließend die alte Datei überschreibt. Die neue Datei /etc/shadow besitzt damit keinen SELinux-Kontext.

Um sicherzustellen, dass alle Dateien (inkl. der /etc/shadow) während des Bootvorgangs mit einem SELinux-Label versehen werden, muss die Datei autorelabel im aktuellen Verzeichnis erstellt werden:

sh-4.2# touch /.autorelabel

Wichtig: Sämtliche Dateien und Verzeichnisse werden erneut mit einem SELinux-Label versehen. Dies kann bei großen Dateisystemen einige Zeit dauern. Um Zeit zu sparen, können Dateisysteme (außer dem Dateisystem auf dem sich die /etc/shadow befindet) in der /etc/fstab auskommentiert werden. Nachdem das SELinux-Relabeling durchgeführt und das System gestartet wurde, können diese wieder eingehängt werden.

Abschließend verlässt man durch zweimalige Eingabe von exit zuerst die chroot-Umgebung und anschließend die Debug-Shell der Ram-Disk (vgl. Abbildung 4). Das System setzt den Bootvorgang an der Stelle fort, an der dieser unterbrochen wurde.

autrelabel

Abbildung 4

Es werden zunächst sämtliche Dateien von SELinux relabelt und anschließend ein Neustart ausgeführt.

Hinweis: Vergisst man die Datei .autorelabel zu erstellen und wird SELinux im Modus „Enforcing“ ausgeführt, kann man sich nach einem Neustart nicht am System anmelden. Man muss dann erneut booten und obige Schritte ausführen, um die Datei erstellen zu können.

Wurden die oben aufgeführten Schritte erfolgreich angewendet, kann man sich nun mit dem vergebenen Passwort am System anmelden und hat damit die Kontrolle zurückgewonnen.

Auch wenn ich diese Anleitung mehrere Male erfolgreich getestet habe, wünsche ich uns allen, dass wir sie möglichst niemals brauchen werden.

SELinux Booleans

Bei SELinux Booleans handelt es sich um kleine Schalter, mit denen sich das Verhalten der SELinux-Richtlinien beeinflussen lässt. Dieser Artikel knüpft an die „Einführung in das grundlegende Konzept von SELinux“ an und erläutert die Verwendung von SELinux Booleans anhand eines einfachen Beispiels.

Hinweis: Das Beispiel aus diesem Artikel wurde auf einem RHEL/CentOS 7.3 getestet. Unter CentOS 7.2 funktioniert die hier gezeigte Konfiguration nicht. Für Details wird auf das Topic1 im CentOS-Support-Forum verwiesen.

Im Einführungsartikel2 wurde SELinux dazu genutzt, um den Zugriff des Apache auf das DocumentRoot-Verzeichnis /var/www/html zu beschränken. Nun möchte der Webmaster den Benutzern gestatten, Webseiten über ihre HOME-Verzeichnisse zu veröffentlichen und aktiviert dazu die Konfiguration für das Modul Userdir.3 4 5

[root@centos ~]$ cat /etc/httpd/conf.d/userdir.conf

    UserDir enabled
    UserDir public_html



    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS


[root@centos ~]#

Nun kann ein Benutzer in seinem HOME-Verzeichnis den Ordner public_html erstellen und eine test.txt-Datei erstellen:

[jkastning@centos ~]$ mkdir public_html
[jkastning@centos ~]$ sudo chmod 711 /home/jkastning/
[jkastning@centos ~]$ sudo chmod 755 public_html/
[jkastning@centos ~]$ vim public_html/test.txt

Hello User

Nach einem Neustart des Dienstes httpd sollte sich nun die Datei index.html aus dem Benutzerverzeichnis abrufen lassen. Statt dessen wird der Zugriff verweigert.

apache_userdir_forbidden

httpd_enable_homdirs –> off

In den Logdateien finden sich Hinweise, die auf SELinux als Ursache hindeuten.

[root@centos ~]# tail /var/log/audit/audit.log|grep AVC
type=AVC msg=audit(1480446615.354:844): avc:  denied  { getattr } for  pid=23150 comm="httpd" path="/home/jkastning/public_html/index.html" dev="sda1" ino=1052157 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file

[root@centos ~]# tail /var/log/messages | grep SELinux
Nov 29 20:10:44 centos setroubleshoot: SELinux is preventing httpd from getattr access on the file /home/jkastning/public_html/index.html. For complete SELinux messages. run sealert -l 13419731-cedd-4433-abb7-b2e7715d5636

Um weitere Informationen zu erhalten, führen wir das Kommando aus /var/log/messages aus (Ausgabe gekürzt):

[root@centos ~]# sealert -l 13419731-cedd-4433-abb7-b2e7715d5636
SELinux is preventing httpd from getattr access on the file /home/jkastning/public_html/index.html.

*****  Plugin catchall_boolean (24.7 confidence) suggests   ******************

If you want to allow httpd to enable homedirs
Then you must tell SELinux about this by enabling the 'httpd_enable_homedirs' boolean.
You can read 'None' man page for more details.
Do
setsebool -P httpd_enable_homedirs 1

In der obigen Ausgabe wird neben der Ursache auch gleich die Lösung mitgeliefert. Nach der Aktivierung des SELinux Boolean httpd_enable_homedirs kann der Inhalt der Datei index.html im Webbrowser abgerufen werden.

apache_userdir_allowed

httpd_enable_homedirs –> on

Damit wurde eine weitere Funktionalität von SELinux kurz vorgestellt. Für weiterführende Informationen sei auf die Manpages booleans(8)6, getsebool(8)7 und setsebool(8)8 verwiesen.

Datenpanne im Internet – Bin ich betroffen?

Sie passieren ständig – Datenpannen1 im Internet. Und die Abstände zwischen ihnen werden gefühlt immer kürzer. In diesem Artikel möchte ich euch einen Weg aufzeigen, wie ihr selbst schnell und einfach feststellen könnt, ob ihr selbst von einer Datenpanne betroffen seid. Im Gegensatz zu vielen anderen Artikeln auf diesem Blog versuche ich dabei auf technische Details so weit wie möglich zu verzichten, um den Artikel allgemeinverständlich zu gestalten.

Datenpannen sind Verstöße, gegen die Datensicherheit und den Datenschutz, bei denen Staatsgeheimnisse, Betriebsgeheimnisse oder personenbezogene Daten Unberechtigten vermutlich oder erwiesenermaßen bekannt geworden sind. – Quelle: Deutschsprachige Wikipedia: Datenpanne

Und Datenpannen können überall passieren. Im Online-Shop, dem Online-Auktionsportal, im Online-Banking, in Tauschbörsen, in sozialen Netzwerken und auch im Cloud-Speicher-Dienst, dem wir unsere Dateien anvertrauen. Wikipedia listet einige bedeutende Vorfälle2, die in den vergangenen Jahren bekannt wurden.

Doch wie kann man nun überprüfen, ob man selbst von einer solchen Panne betroffen ist? Eine erfreulich einfache Möglichkeit bietet die Webseite https://haveibeenpwned.com/.3 4

https://haveibeenpwned.com

https://haveibeenpwned.com – Prüfe, ob einer deiner Accounts durch eine Datenpanne kompromittiert wurde.

Die Bedienung der Seite ist, wie bereits erwähnt, erfreulich einfach. Man trägt den zu überprüfenden Benutzernamen bzw. E-Mail-Adresse in das Suchfeld ein und startet die Suche. Das Ergebnis gibt Auskunft darüber, ob der Benutzername bzw. die E-Mail-Adresse von einer Datenpanne betroffen ist und bei welchem Dienst die Informationen stammen. Die folgenden beiden Screenshots zeigen zwei Beispiele. Das erste Beispiel zeigt einen Fall, bei dem die Kompromittierung eines Benutzernamens bis heute nicht bekannt geworden ist. Das zweite Beispiel zeigt die Abfrage einer E-Mail-Adresse, die mit anderen Daten bei einem Datenleck beim Cloud-Speicheranbieter Dropbox abgegriffen wurden.

username-not-compromised

Keine Kompromittierung des Benutzernamens bekannt

compromised-mailaddress

Die kompromittierte E-Mail-Adresse stammt aus einem Datenleck bei Dropbox

Neben der manuellen Überprüfung bietet die Webseite auch die Möglichkeit, eine E-Mail-Adresse zu hinterlegen. Taucht diese E-Mail-Adresse in einem öffentlich bekannt gewordenen Datenbestand auf, erhält man hierüber eine Nachricht an die hinterlegte E-Mail-Adresse.

Was tun, wenn ich betroffen bin?

Stellt man nun fest, dass die geprüften Benutzerdaten kompromittiert sind, sollte man umgehend handeln. Es ist dringend empfohlen, in diesem Fall

  1. die Zugangsdaten (Benutzername, E-Mail-Adressse, Passwort) beim betroffenen Dienst zu ändern.
  2. die Zugangsdaten (Benutzername, E-Mail-Adressse, Passwort) bei allen sonstigen Diensten zu ändern, bei denen die gleichen Zugangsdaten verwendet wurden.

Mit dem zweiten Schritt soll sichergestellt werden, dass mit den kompromittierten Benutzerinformationen noch weitere Benutzerkonten bei anderen Online-Diensten gekapert werden können.

Um den Umgang und die Verwaltung von Benutzernamen und Passwörtern so komfortabel wie möglich zu gestalten, empfehle ich die Verwendung eines Passwortmanagers wie z.B. KeePass.5 6 7

Das lokale Paketarchiv aufräumen

Während ich im Artikel „Automatische Installation von Sicherheitsupdates“ beschrieben habe, wie man Sicherheitsupdates unter Ubuntu automatisch installieren lassen kann, werde ich hier kurz beschreiben, wie das lokale Paketarchiv automatisch bereinigt werden kann.

In der Datei /etc/apt/apt.conf.d/10periodic gibt es unter anderem den folgenden Eintrag:

APT::Periodic::AutocleanInterval "0";

Dieser Wert gibt an, in welchem Intervall (in Tagen) das lokale Archiv der Paketquellen bereinigt werden soll. Dieser Wert steht standardmäßig auf „0“. Damit wird das Paketarchiv gar nicht automatisch bereinigt. Um dies zu ändern trägt man hier einfach einen Wert seiner Wahl ein. So lasse ich das Paketarchiv bspw. alle 28 Tage bereinigen:

APT::Periodic::AutocleanInterval "28";

Viele Grüße
Tronde

Häufig benötigte MySQL-Befehle

In diesem Artikel dokumentiere ich die von mir am häufigsten verwendeten und am schnellsten vergessenen MySQL-Befehle. So muss ich sie nicht jedes Mal in der offiziellen Dokumentation nachschlagen.1

Der Vollständigkeit halber beginne ich mit dem Befehl, mit dem man sich mit einem MySQL-Server verbindet, welcher auf dem localhost läuft.

$ mysql -u BENUTZERNAME -p
Password: 

Eine neue Datenbank kann mit dem folgenden Befehl erstellt werden2:

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
    [create_specification] ...

create_specification:
    [DEFAULT] CHARACTER SET [=] charset_name
  | [DEFAULT] COLLATE [=] collation_name

Beispiel:

CREATE DATABASE db_name;

Einen MySQL-Benutzeraccount erstellt man mit dem Befehl3:

CREATE USER user_specification [, user_specification] ...

user_specification:
    user [ identified_option ]

auth_option: {
    IDENTIFIED BY 'auth_string'
  | IDENTIFIED BY PASSWORD 'hash_string'
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin AS 'hash_string'
}

Beispiel:

CREATE USER 'pusemuckel'@'localhost' IDENTIFIED BY 'password';

Mit dem folgenden Kommando werden dem erstellten Benutzer Zugriffsrechte auf die erstellte Datenbank gewährt.4 Mit diesen Berechtigungen kann der Benutzer neue Tabellen in der Datenbank erstellen, Daten in Tabellen einfügen oder auch die gesamte Datenbank löschen.

GRANT ALL PRIVILEGES ON db_name.* TO 'pusemuckel'@'localhost';

Die letzten beiden Schritte können auch verkürzt mit folgendem Kommando ausgeführt werden:

GRANT ALL ON db_name.* TO 'pusemuckel'@'localhost' IDENTIFIED BY 'password';

Hat man neue Benutzer angelegt, oder die Berechtigungen bestehendender Benutzer geändert, werden die neuen Berechtigungen mit dem folgenden Kommando geladen:

FLUSH PRIVILEGES;

So, nun muss ich mich zukünftig nur noch daran erinnern, hier nachzuschauen, wenn mir mal wieder die Syntax entfallen ist. 😉

SpamAssassins Erkennungsrate mit SA-Learn verbessern

Unter „Training für SpamAssassin“ wurde bereits erklärt, wie man mit dem Hilfsprogramm sa-learn das Erkennungsverhalten von SpamAssassin trainieren kann.

An dieser Stelle möchte ich noch mal ein konkretes Beispiel dazu dokumentieren.

Auf meinem Server verwende ich die Maildir-Verzeichnisstruktur, zum Speichern meiner E-Mails.

In meinem Fall befinden sich die bereits gelesenen E-Mails im Posteingang im Pfad /var/mail/vmail/example.org/username/mail/cur. Die in diesem Ordner liegenden E-Mails sind kein Spam. Dies kann SpamAssassin mit dem folgenden Befehl mitgeteilt werden:

# sa-learn --ham /var/mail/vmail/example.org/username/mail/cur/ --progress
100% [=========================================================================================================================]  10.43 msgs/sec 00m01s DONE
Learned tokens from 13 message(s) (18 message(s) examined)

Spam landet in meinem Fall im Pfad /var/mail/vmail/example.org/username/mail/Junk/cur. Diese Mails können mit dem folgenden Kommando verarbeitet werden.

sa-learn --spam /var/mail/vmail/example.org/username/mail/Junk/cur

Weitere Informationen findet man auf der offiziellen Homepage von SpamAssassin.