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]-->

Linux-Citrix-Client installieren

Neuerdings braucht der Citrix-Client auf Linux die libXm.so.3 – aber wo ist die?

Die libXm gehört zum Paket openMotif, welches sich einfach über Yast installieren lässt. Bei 64-Bit-Systemen muss man leider die 32-Bit-Version von openMotif installieren, da Citrix die Software noch nicht auf 64-Bit portiert hat. Dazu im Yast zusätzlich das Paket openmotif-libs-32bit auswählen.

Allerdings wird hier bei SuSE 10.2 die neuere Version 2.3 installiert, die die libXm.so.4 mitbringt. Das ist aber nicht weiter schlimm, denn man kann als root einen Link anlegen:

ln -s /usr/lib/libXm.so.4.0.0 /usr/lib/libXm.so.3

Danach klappt’s auch mit Citrix 😉

Update 06.12.2013

Heute wollte ich die 64bit-Version des Citrix-Receivers, wie der Client nun heißt, installieren. Klar, dass das nicht „mal eben“ funktioniert:

# rpm -Uhv ICAClient-13.0.0.256735-0.x86_64.rpm
error: Failed dependencies:
        libcurl.so.4 >= 7.19.1 is needed by ICAClient-13.0.0.256735-0.x86_64
        libxerces-c-3.1.so is needed by ICAClient-13.0.0.256735-0.x86_64
        libwebkitgtk-1.0.so.0 is needed by ICAClient-13.0.0.256735-0.x86_64

Ein Blick in die Paketverwaltung zeigte aber, dass alle Bibliotheken installiert sind – in der 64bit-Version, logischerweise. Sollte etwa der ICA-Client, obwohl als 64bit deklariert, wieder die 32bit-Versionen der Bibliotheken haben wollen? Ja, genauso war’s. Und bei libwebkitgtk musste es auch die 1er Version sein, die 3er half nicht.

Die libxerces gibt es bei SuSE nicht in der Paketverwaltung, aber in einem Post im OpenSuSE-Forum fand sich ein passender Link.

Speed und Duplex eines Interfaces beim Booten einstellen

Manchmal muss ein Netzwerk-Interface fest auf eine Geschwindigkeit und/oder Duplex-Verfahren eingestellt werden, weil die Autonegoation nicht funktioniert.

Grundsätzlich ist die Autonegoation, also die selbstständige, optimale Einstellung zweier verbundener Netzwerkports eine gute Sache – wenn sie funktioniert und sie auch bei beiden Ports eingeschaltet ist (siehe auch „Duplex Mismatch und Autonegotiation im Ethernet„). Wenn nicht, müssen die Ports manuell konfiguriert werden. Man kann diese Einstellungen mit dem Werkzeug ethtool vornehmen, aber beim Booten des Rechners wird das Interface wieder auf Auto stehen.

Leider gibt es kein einfachen Konfigurationsparameter (z.B. in der Interfacekonfiguration unter /etc/sysconfig/network), der das bewerkstelligt. Damit diese Einstellungen auch beim Booten wirksam werden muss bei SuSE 10.x ein Script angelegt werden, welches aufgerufen wird, wenn das Interface gestartet wurde. Dies ist ein sehr universelles Konzept, welches auch viele andere Möglichkeiten bietet. Grundsätzlich gibt es zwei Möglichkeiten, ein Script beim Starten ausführen zu lassen:

  • Ein Script in /etc/sysconfig/network/if-up.d
  • Ein Script mit der Variablen POST_UP_SCRIPT in der Interfacekonfigurationsdatei /etc/sysconfig/network/ifcfg-* angeben

Bei der ersten Möglichkeit wird das Script bei jedem Interface ausgeführt, man muss daher die übergebenen Parameter analysieren und ein Fehler im Script kann die gesamte Netzkonfiguration des Rechners durcheinander bringen.

Ich verwende daher die zweite Möglichkeit, bei dem ein spezielles Script für das gewünschte Interface erstellt wird. Man kann aber auch ein universelles Script erstellen, welches die übergebenen Parameter analysieren. Da es aber nur für die Interface ausgeführt wird, die dieses Script auch in POST_UP_SCRIPT stehen haben, ist das sicherer als die erste Methode. Wer mehr zu den beiden Verfahren wissen möchte, dem seinen die Man-Pages zu ifup und ifcfg empfohlen.

Ich habe nun also in der Konfigurtationsdatei für die betreffende Netzwerkkarte die folgende Zeile hinzugefügt:

POST_UP_SCRIPT='post_up_eth2'

Das Script sieht dann so aus:

#!/bin/sh
# Stellt das Interface auf 100 Full ein
#echo $0 $1 $2 $3 $4 $5
CONF_NAME=$1
HW_NAME=$2

ethtool -s $HW_NAME autoneg off speed 100 duplex full

ethtool $HW_NAME

Wird in der Konfigdatei kein Pfad mit angegeben, so wird das Script in /etc/sysconfig/network/scripts erwartet.