Archiv des Autors: romeofox

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.

Dateinamen mit Leerzeichen auf der Kommandozeile verarbeiten

Dateinamen, die Leerzeichen enthalten, machen auf der Kommandozeile oder in Scripten häufig Ärger, da das Leerzeichen meist als Trennzeichen zwischen den Parametern dient. hier nun ein paar Tricks, wie man die Probleme umschiffen kann.

Will man beispielsweise untersuchen, wieviel Platz die Dateien und Unterverzeichnisse des aktuellen Verzeichnisses jeweils einnehmen, kann man das mit

ls -A -1 | du -sh

machen. Aber das funktioniert nur für Dateinamen und Verzeichnisse, die keine Leerzeichen enthalten. Um auch solche zu verarbeiten muss man die folgende Kommandokette verwenden:

find . -maxdepth 1 -print0 | xargs -0 du -sh

Wir benutzen hier find, weil dieses die gefunden Namen durch das Argument -print0 als sog. nullterminierten String ausggeben kann. Dies teilen wir xargs mit dem Schalter -0 mit, wodurch xargs automatisch alle Leerzeichen etc. escaped an das eigentliche Kommando „du -sh“ weitergibt. Damit find nicht auf die Idee kommt, auch die Unterverzeichnisse zu durchsuchen, begrenzen wir die Suche mit „-maxdepth 1“ auf das angegebene Verzeichnis.

Unter Linux (bzw. mit GNU-ls) kann man auch die Option -Q des ls Kommandos nutzen, welches die Namen in Anführungszeichen setzt. Xargs ist aber trotzdem erforderlich:

/bin/ls -A1Q | xargs du -sh

[Wird fortgesetzt…]