Backup-Differenzen mit rsync feststellen und zurückspielen

Sowas passiert: Platten-Crash! Aber man hatte ja vorgesorgt und ein Platten-Image gezogen und auch immer schön die wichtigsten Dateien und Verzeichnisse in Sicherheit gebracht, z.B. mit dem in „Verzeichnisse auf einen anderen Rechner übertragen“ beschriebenen Verfahren. Das Image ist schnell auf die neue Platte gespielt, aber wie bekommt man nun die aktuellen Backupdateien wieder ins System, ohne sich beispielsweise die neuere LVM-Config zu zerschießen?

Hier kann das Tool rsync sehr hilfreich sein – auch wenn die Daten gar nicht mit rsync gesichert wurden. Zunächst wechselt man in das Verzeichnis, in dem die Backupdateien liegen. Hatte man ein (komprimiertes) Tar-Archiv angelegt, muss dieses in ein temporäres Verzeichnis entpackt werden.

Nun kann der Inhalt dieses Verzeichnisses gegen den wiederhergestellten Rechner verglichen werden:

rsync -rznciuK -e ssh ./ root@meinLinuxPC:/ | grep -v skipp

Durch den Schalter -n werden keine Daten übertragen, sondern nur angezeigt, welche Dateien aus dem Backup neuer sind als auf dem wiederhergestellten System:

  <fcsT.... etc/SnmpAgent.d/snmpd.conf
  <fcsT.... etc/rc.config.d/SnmpHpunix
  <fcsT.... etc/rc.config.d/SnmpMaster
  <fcsT.... etc/rc.config.d/SnmpMib2
  <fcsT.... var/spool/cron/crontabs/root

Zur Bedeutung von <fcsT.... siehe man rsync, –itemize-changes.

Wenn man die Dateien nicht von Hand übertragen will, kann man das auch rsync machen lassen:

rsync -rzciuKb --suffix=~rsync -e ssh ./ root@meinLinuxPC:/ | grep -v skipp

Hier fehlt der Schalter -n, der oben dafür sorgt, dass keine Dateien übertragen werden. Die Optionen -b und --suffix=~rsync sorgen dafür, dass auf dem Zielrechner die Original-Dateien mit dem Suffix ~rsync erhalten bleiben.

Das Quartal mit date berechnen

Das Unix-Kommando date kennt viele Format-Parameter aber leider keinen, der uns das Quartal ausgibt. Zum Glück lässt sich das aber mit Hilfe von expr berechnen.

Wir können mit dem date-Befehl einen Ausdruck erstellen, den expr dann für uns ausrechnet. Wir bekommen das das aktuelle Quartal oder, wenn wir mit -d ein anders angeben, das des gefragten Datums:

expr `date "+( %m - 1 ) / 3 + 1"`

expr `date -d "2007-05-01" "+( %m - 1 ) / 3 + 1"`

Dateien an Hand des Datums und der Uhrzeit finden

Manchmal muss man eine Datei finden, von der man nur weiß, wann sie zuletzt geändert wurde. Weiß man, dass das vor 3 Tagen war, hilft einem die Option -mtime +3 des Befehls find. Hat man aber ein Datum und eine Uhrzeit, muss man ein wenig tricksen.

Man kann hier die Option -newer zusammen mit einer Referenzdatei verwenden. Diese Referenzdatei kann mit touch erstellt werden. Da wir einen bestimmten Zeitpunkt suchen, brauchen wir noch eine zweite Referenzdatei, da -newer sonst alle neueren Dateien ausgibt.

$ touch -t 11142104 /tmp/tmp_start
$ touch -t 11142105 /tmp/tmp_end
$ find /opt -newer /tmp/tmp_start ! -newer /tmp/tmp_end

Dies findet Dateien im Verzeichnis /opt und darunter, die zuletzt am 14.November um 21:04 Uhr modifiziert wurden.

Dieses Beispiel funktioniert unter Linux, aber auch unter HP-UX, dessen Befehle find und touch leider nicht so viele Optionen kennen wie die Linux-Versionen

Den jeweils aktuellesten Datensatz zur jeweiligen Kategorie ermitteln

Eine immer wiederkehrende Problemstellung: In einer Tabelle sind zu verschiedenen Kategorien mehrere Einträge gespeichert (z.B. ein Forum o.ä.). Nun gilt es, zu jeder Kategorie den jeweils aktuellsten Datensatz zu ermitteln.

Wir haben beispielsweise folgende Tabelle:

CREATE TABLE `tab1` (
  `id` int(11) default NULL,
  `cat` int(11) default NULL,
  `titel` char(100) default NULL,
  `time` time default NULL
);

Die Tabelle enthält natürlich auch Daten:

+------+------+------------+----------+
| id   | cat  | titel      | time     |
+------+------+------------+----------+
|    1 |    1 | datensatz1 | 00:00:15 |
|    2 |    2 | datensatz2 | 00:01:00 |
|    3 |    3 | datensatz3 | 00:02:00 |
|    4 |    1 | datensatz4 | 00:01:00 |
|    5 |    2 | datensatz5 | 00:02:15 |
|    6 |    3 | datensatz6 | 00:01:15 |
+------+------+------------+----------+

(insert into tab1 values (1, 1, ‚datensatz1′, ’00:00:15‘), (2, 2, ‚datensatz2′, ’00:01:00‘), (3, 3, ‚datensatz3′, ’00:02:00‘), (4, 1, ‚datensatz4′, ’00:01:00‘), (5, 2, ‚datensatz5′, ’00:02:15‘), (6, 3, ‚datensatz6′, ’00:01:15‘);)

Um nun das gewünschte Ergebnis zu bekommen, benutz man eine sog. Self-Left-Join, also einen Left-Join mit der selben Tabelle:

SELECT x.* FROM tab1 AS x LEFT JOIN tab1 AS y
  ON x.cat = y.cat AND x.time < y.time
  WHERE y.id IS NULL ORDER BY cat;

+------+------+------------+----------+
| id   | cat  | titel      | time     |
+------+------+------------+----------+
|    4 |    1 | datensatz4 | 00:01:00 |
|    5 |    2 | datensatz5 | 00:02:15 |
|    3 |    3 | datensatz3 | 00:02:00 |
+------+------+------------+----------+

Nach einem Post von Björn Brinkhoff (bjoern-at-brinkhoff-dot-org) in der deutschen MySQL-Mailinglist mysql-de@lists.mysql.com am 13.11.2007

Netzmasken von Subnetzen und Anzahl der Adressen

Es gibt zwei verschiedene Arten, eine Netzmaske zu schreiben. Hier eine kleine Tabelle als Übersicht für die Class-C-Subnetze:

Netzmaske Kurzform Anzahl
Adressen
255.255.255.255 /32 1
255.255.255.252 /30 4
255.255.255.248 /29 8
255.255.255.240 /28 16
255.255.255.224 /27 32
255.255.255.192 /26 64
255.255.255.128 /25 128
255.255.255.0 /24 256

KDE mit Keychain

Damit man nicht immer ständig die Passphrase für seinen SSH-Key eingeben muss ist keychain das passende Werkzeug. Normalerweise wird der entsprechende Aufruf in die bashrc o.ä. eingetragen. Bei grafischen Oberflächen ist das jedoch nicht die erste Wahl.

Bei KDE speichert man besser ein kleines Shellscript im persönlichen Autostart-Verzeichnis ~/.kde/Autostart

#!/bin/sh
keychain --quiet ~/.ssh/id_dsa
source ~/.keychain/${HOSTNAME}-sh

Wenn dieses Script ausführbar ist, wird der Anwender beim nächsten Start von KDE per Dialog nach der Passphrase gefragt. Dazu darf natürlich kein entspr. Eintrag in der .bashrc oder .profile vorhanden sein, da dieser sonst unserem kleinen Script eventuell zuvor kommt.

String in der Shell in Groß- oder Kleinbuchstaben wandeln

Mitunter will man in einem Shell-Script einen String ist Groß- oder Kleinbuchstaben wandeln. Das lässt sich recht einfach mit dem Kommando tr bewerkstelligen, welches auf vielen Systemen verfügbar ist.

So werden Kleinbuchstaben in Großbuchstaben gewandelt:

VAR=öäüß
echo $VAR
VAR=`echo $VAR|tr "[:lower:]" "[:upper:]"`
echo $VAR

Durch die Verwendung von [:lower:] und [:upper:] werden auch Umlaute berücksichtigt, was bei [a-z] bzw. [A-Z] nicht der Fall wäre.

Die umgekehrte Richtung funktioniert logischer Weise so:

VAR=GROSSÄÜÖ
echo $VAR
VAR=`echo $VAR|tr "[:upper:]" "[:lower:]"`
echo $VAR

Dateien finden, die nicht von allen gelesen werden können

Manchmal muss man die Dateien finden, deren Rechte so gesetzt sind, dass sie nicht von allen gelesen werden können. Mit

find . -type f -not -perm -0004 -ls

findet man alle Dateien im aktuellen Verzeichnis und darunter, deren Worldreadable-Bit nicht gesetzt ist.

Und so macht man sie für alle lesbar:

find . -type f -not -perm -0004 -exec chmod -c a+r {} ;

Das gleiche für Verzeichnisse:

find . -type d -not -perm -0004 -exec chmod -c a+rx {} ;

Browserweiche mit conditional comments für IE 7

Bislang wurden bei Browserweichen meist nur zwischen Internet-Explorer und Nicht-Internet-Explorer unterschieden. Nun muss aber häufig auch erkannt werden, ob es nicht vielleicht ein IE 7 ist.

Denn dieser Browser hat nun einige der Bugs der Vorgängerversionen behoben und die Hacks dürfen hier nicht mehr zur Anwendung kommen. Grundsätzlich kann man mit

<!--[if lt IE 7]>
MSIE der alten Art (4.0 ... 6.0)
<![endif]-->

alle alten IE filtern.

Wird eine genauere Differenzierung benötigt, können die „Conditional Comments“ auch verschachtelt werden:

<!--[if lt IE 7]>
  <!--[if gte IE 5.5]>
  IE 5.5 ... 6.0
  <![endif]-->
  <!--[if lt IE 5.5]>
  4.0 ... 5.0
  <![endif]-->
<![endif]-->