Impressum
Frank Seitz Hermann-Rohwedder-Str. 16 25462 Rellingen E-Mail: fs Telefon: +49 176 78243503 Kurzprofil CPAN Haftungsausschluss KategorienAbonnierenArchiv
|
Dienstag, 15. Mai 2012Perl: Text im Character Encoding des Systems ausgebenUm Texte mit Non-ASCII-Zeichen korrekt auf ein Terminal bzw. in ein Terminal-Window ausgeben zu können, ist es notwendig, das Character Encoding der Systemumgebung zu kennen. Diese Einstellung steht typischerweise auf der Environment-Variablen $LANG. Unter Perl stellt das Core-Modul I18N::Langinfo eine Schnittstelle zur Abfrage der Locale-Umgebung zur Verfügung. Die Abfrage für das Character-Encoding sieht so aus: 1 use I18N::Langinfo (); 2 3 my $charset = I18N::Langinfo::langinfo(I18N::Langinfo::CODESET()); 4 print $charset,"\n"; Der Text muss vor Ausgabe in dieses Encoding gewandelt werden. Dies leistet die Funktion encode(): 1 use Encode (); 2 3 print Encode::encode($charset,$text); Eine andere Möglichkeit ist, alle Ausgaben durch einen I/O-Layer umwandeln zu lassen. Mittels binmode() wird der entsprechende I/O-Layer auf dem Ausgabekanal, hier STDOUT, registriert: 1 binmode STDOUT,":encoding($charset)"; 2 print $text; Ein typischer Anwendungsfall ist die Ausgabe der Programmdokumentation auf STDOUT oder STDERR. Diese soll unabhängig vom konkret eingestellten Encoding auf $LANG immer richtig auf dem Terminal erscheinen. Im folgenden Beispiel bekommen wir die Doku UTF-8 kodiert von pod2text geliefert, wandeln sie mit encode() in das Encoding des Systems und geben sie aus: 1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 6 =encoding utf8 7 8 Dies ist ein Test: ÄÖÜäöüß 9 10 =cut 11 12 use I18N::Langinfo (); 13 use Encode (); 14 15 # Programmdokumentation erzeugen. Die hereinkommenden Daten sind 16 # UTF-8 encoded. Durch Aufruf von decode() teilen wir Perl dies mit. 17 my $text = Encode::decode('UTF-8',qx/pod2text $0/); 18 19 # Encoding des Systems ermitteln 20 my $charset = I18N::Langinfo::langinfo(I18N::Langinfo::CODESET()); 21 22 # Dokumentation im Encoding des Systems ausgeben 23 print Encode::encode($charset,$text); 24 25 # eof Freitag, 23. März 2012Lookup-Trigger für Oracle und PostgreSQLGegeben ist eine Tabelle <table> mit einer Kolumne <x>, deren Wert frei manipuliert werden kann, und einer Kolumne <y>, deren Wert funktional von <x> abhängt (also nicht frei manipuliert werden kann). Die Abbildung von <x> auf <y> ist in einer Lookup-Tabelle <lookup_table> definiert, die jedem Wert <x> den entsprechenden Wert <y> zuordnet. Aufgabe: Der <y>-Wert soll in <table> gespeichert werden und stets konstitent zu <x> sein. Der Wert von <y> soll nicht erst bei Abfrage ermittelt werden. Im Prinzip ist das eine unerwüschte Redundanz, die aber aus praktischen Gründen sinnvoll sein kann. Die Anforderung lässt sich durch einen BEFORE INSERT OR UPDATE-Trigger erfüllen, der beim Einfügen oder Ändern in <table> den <y>-Wert via <x> in <lookup_table> ermittelt und auf <table>.<y> überträgt. Es folgt die Lösung für Oracle und PostgreSQL. Oracle1 CREATE OR REPLACE TRIGGER <tigger> BEFORE INSERT OR UPDATE 2 ON <table> FOR EACH ROW 3 BEGIN 4 SELECT 5 <y> 6 INTO 7 :new.<y> 8 FROM 9 <lookup_table> 10 WHERE 11 <x> = :new.<x>; 12 END; PostgreSQL1 CREATE FUNCTION <trigger_func>() RETURNS trigger AS $$ 2 BEGIN 3 SELECT 4 <y> 5 INTO STRICT 6 NEW.<y> 7 FROM 8 <lookup_table> 9 WHERE 10 <x> = NEW.<x>; 11 12 RETURN NEW; 13 END; 14 $$ LANGUAGE plpgsql; 15 16 CREATE TRIGGER <trigger> BEFORE INSERT OR UPDATE 17 ON <table> FOR EACH ROW 18 EXECUTE PROCEDURE <trigger_func>(); Der Code ist bei beiden Datenbanksystemen ähnlich, die Unterschiede sind im Wesentlichen:
Dienstag, 28. Februar 2012PostgreSQL: Notizen zum psql Kommando-Interpreter
Startup-Datei anlegen/ändern: $ vi ~/.psqlrc Die Kommandos in der Datei führt der Interpreter beim Start aus. Hier können persönliche Einstellungen vorgenommen werden. Z.B. kann man dort den Pager aus- und die Zeitmessung einschalten. Pager abschalten: <db>=# \pset pager off Pager usage is off. Zeitmessung einschalten: <db>=# \timing on Timing is on. Nützliche interaktive Kommandos: Liste der Schemata: <db>=# \dn ... Liste der Tabellen eines Schemas: <db>=# \dt <schema>.* ... Tabelle, View oder Sequenz beschreiben: <db>=# \d <object> ... Spezielle SQL-Anweisungen: Liste der Runtime-Parameter: <db>=# show all; ... Mittwoch, 8. Februar 2012Java SE 7 JDK unter Linux installieren
Das Java SE (Standard Edition) Devolpment Kit (JDK) gibt es hier. Wir folgen dem Workflow und laden die gewünschten Archiv-Dateien herunter. Für Standard Edition 7 sind es für Linux x86 die Dateien:
Wir gehen in ein beliebiges Verzeichnis (z.B. /opt/java) und entpacken die Dateien dort: $ tar xvzf jdk-7u2-linux-i586.tar.gz $ tar xvzf jdk-7u2-linux-i586-demos.tar.gz $ unzip jdk-7u2-apidocs.zip $ mv docs jdk1.7.0_02 Im Unterverzeichnis jdk1.7.0_02 befindet sich nun das JDK einschließlich Dokumentation (Unterverzeichnis docs mit docs/index.html als Startseite) und Beispielen (Unterverzeichnisse demo und samples). Wir nutzen diese Java-Installation, indem wir das Environment darauf einstellen: $ export JAVA_HOME=`pwd`/jdk1.7.0_02 $ PATH=$JAVA_HOME/bin:$PATH Programm "Hello world": $ vi HelloWorldApp.java
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Klasse kompilieren und ausführen: $ javac HelloWorldApp.java $ java HelloWorldApp Hello World! Java SE 6 JDKFür Standard Edition 6 sind es für Linux x86 nur zwei Archiv-Dateien, da das JDK-Archiv die Beispiele mit enthält:
Das Auspacken verläuft geringfügig anders, da die Daten in ein Shell-Archiv eingepackt sind: $ sh jdk-6u30-linux-i586.bin $ unzip jdk-6u30-apidocs.zip $ mv docs jdk1.6.0_30 Das JDK befindet sich in Unterverzeichnis jdk1.6.0_30. Dienstag, 7. Februar 2012Notizen zu Amazons eBook-Reader Kindle 4
eBook-ManagementEine leistungsffähiges Werkzeug zur Verwaltung und Konvertierung von eBooks ist das eBook Management-System Calibre. Installation unter Debian: # apt-get install calibre eBook per Kommandozeile in Calibre-Bibliothek kopieren$ calibredb add FILE.azw Private Kopien von DRM-geschützten eBooks anlegenDafür existiert das Calibre-Plugin K4MobiDeDRM. Siehe: Links
Donnerstag, 19. Januar 2012Debian GNU/Linux von USB-Stick booten
Rescue SystemHat man die Kontrolle über ein Linux-System verloren (es bootet nicht mehr, Anmelden als root ist nicht möglich, o.ä.) ist es nützlich ein Rescue-System zu haben, von dem aus man das defekte System untersuchen und ggf. reparieren kann. Ein solches Rescue-System lässt sich leicht auf einem USB-Stick installieren. Hierzu holt man sich das Image eines Live-Systems von einem Debian-Mirror und kopiert es 1:1 auf den USB-Stick. Die Live-Systeme von Debian finden sich unter http://www.debian.org/CD/live/. Sie basieren auf dem aktuellen Stable-Release für die Architekturen i386 und amd64 und unterscheiden sich in der Desktop-Umgebung (Gnome, KDE, LXDE, Xfce oder Terminal): debian-live-<version>-<arch>-gnome-desktop.<ext> debian-live-<version>-<arch>-kde-desktop.<ext> debian-live-<version>-<arch>-lxde-desktop.<ext> debian-live-<version>-<arch>-xfce-desktop.<ext> debian-live-<version>-<arch>-rescue.<ext> debian-live-<version>-<arch>-standard.<ext> Hierbei ist: <version> die Versionsnummer des Stable-Release (aktuell 6.0.3) <arch> die Prozessor-Architektur (amd64 oder i386) <ext> die Dateiendung .iso oder .img Da jedes Live-System aus nur einer Datei besteht und bootfähig ist, gestaltet sich das Herunterladen und Installieren sehr einfach: # wget <file> # dd if=<file> of=/dev/sd<x> bs=1M # sync Hierbei ist: <file> eine der obigen Dateien <x> der Device-Buchstabe des USB-Stick Fertig. Vorsicht! Ein falscher Device-Name kann Daten auf anderen Geräten als dem USB-Stick oder gar das System komplett zerstören. Er sollte daher akribisch geprüft werden. Er lässt sich z.B. mit fdisk -l ermitteln. Sollte der Stick beim Einstecken automatisch gemountet worden sein, was wahrscheinlich ist, muss er vor Ausführung des dd-Kommandos erst mit umount ausgehängt werden. Zum Booten vom Stick stellt man die Bootreihenfolge im BIOS-Setup entweder dauerhaft um oder ändert sie "on the fly" beim Bootvorgang, durch Drücken der Taste, die eine Auswahl des Boot-Device erlaubt (z.B. ESC). Beim Eee PC Asus 1001PX lässt sich der Stick nur mit der letzterer Methode booten. Ein automatisches Booten vom Stick funktioniert nicht, es wird immer von der Festplatte gebootet. Installer für Debian TestingDie Images für das Erzeugen eines Debian-Installers für Testing auf einem USB-Stick (oder einer CD) befinden sich hier: http://www.debian.org/devel/debian-installer/ Businesscard-ISO-ImageDas Businesscard-Image lässt sich vereinfacht auf den USB-Stick bringen, da es in die boot.img-Partition passt. Das NetInst-Image von Testing ist dafür zu groß (siehe NetInst-ISO-Image). # wget -N http://d-i.debian.org/daily-images/<arch>/daily/\
hd-media/boot.img.gz
# wget -N http://cdimage.debian.org/cdimage/daily-builds/daily/\
arch-latest/<arch>/iso-cd//debian-testing-<arch>-businesscard.iso
# zcat boot.img.gz >/dev/sd<x>
# mount /dev/sd<x> /mnt
# cp debian-testing-<arch>-businesscard.iso /mnt
# umount /dev/sd<x>
Hierbei ist:
<arch> die Prozessor-Architektur (i386, amd64, ...)
<x> der Device-Buchstabe des USB-Stick
NetInst-ISO-ImageDas NetInst-Image muss wegen seiner Größe mittels Syslinux auf den USB-Stick gebracht werden. Syslinux benötigt eine Partitionierung mit einer FAT16-Partition à la Device Boot Start End Blocks Id System /dev/sdc1 * 2048 7829503 3913728 6 FAT16 Wie diese erstellt wird, siehe http://wiki.debian.org/BootUsb#Partitioning_the_USB_key. Ferner werden folgende Pakete benötigt: mbr, mtools, syslinux. # wget http://d-i.debian.org/daily-images/<arch>/daily/hd-media/vmlinuz
# wget http://d-i.debian.org/daily-images/<arch>/daily/hd-media/initrd.gz
# http://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/\
<arch>/iso-cd/debian-testing-<arch>-netinst.iso
# install-mbr /dev/sd<x>
# mkdosfs /dev/sd<x>1
mkdosfs 3.0.12 (29 Oct 2011)
# syslinux -i /dev/sd<x>1
# mount /dev/sd<x>1 /mnt
# cp vmlinuz initrd.gz debian-testing-i386-netinst.iso /mnt
# cat >/mnt/syslinux.cfg
default vmlinuz
append initrd=initrd.gz
^D
# umount /dev/sd<x>1
Hierbei ist:
<arch> die Prozessor-Architektur (i386, amd64, ...)
<x> der Device-Buchstabe des USB-Stick
LinksProgrammNAME
debian-to-usb - Erzeuge bootbaren USB-Stick mit Debian Image
USAGE
debian-to-usb [OPTIONS] IMAGE DEVICE
debian-to-usb --get net-inst
debian-to-usb --get businesscard-inst
OPTIONS
--verbose=BOOL (Default: 1)
Gib die ausführenden Kommandos aus.
--help
Diese Hilfe.
IMAGE
Der Dateiname eines Debian Live-Image mit der Endung .iso oder .img
oder einer der beiden Bezeichner
businesscard-inst
Erzeuge Installer aus Businesscard-Image.
net-inst
Erzeuge Installer aus NetInst-Image.
DEVICE
Der Device-Name, unter dem der USB-Stick angesprochen wird. Z.B.
"/dev/sdb". Das Device darf nicht gemountet sein.
Vorsicht! Ein falscher Device-Name kann Daten auf anderen Geräten
oder gar das System zerstören. Er sollte daher akribisch geprüft
werden. Er lässt sich z.B. mit "fdisk -l" ermitteln.
AUTHOR
Frank Seitz, http://www.fseitz.de/
COPYRIGHT
Copyright (C) Frank Seitz, 2012
Freitag, 30. Dezember 2011HTTPS-Server: SSL-Zertifikat erwerben und einrichtenAntragstellung: über Strato V-Server Account, SSL-Zertifikatstyp: thawte SSL123, Kosten: 3,90 EUR/Monat. Private Key erzeugen (mydomain-de.key)# openssl genrsa -des3 -out mydomain-de.key 2048 Generating RSA private key, 2048 bit long modulus ... Der Private Key wird hier im Klartext ohne Passphrase erzeugt. Es ist praktischer, keine Passphrase zu verwenden, da sonst beim Neustart des HTTP-Servers die Passphrase manuell eingegeben werden müsste. Certificate Request erzeugen (mydomain-de.csr)# openssl req -new -key mydomain-de.key -out mydomain-de.csr ... Country Name (2 letter code) [AU]:DE State or Province Name (full name) [Some-State]:BUNDESLAND Locality Name (eg, city) []:STADT Organization Name (eg, company) [Internet Widgits Pty Ltd]:ORGANISATION Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:mydomain.de Email Address []:me@mydomain.de Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Der Certificate Request wird bei Thawte eingereicht. Dies wickelt Strato ab. Die Daten werden über ein Webformular unter "SSL-Verwaltung/Easy SSL" erhoben. Thawte meldet sich per Mail. Auf dem Weg und per Bestätigung übers Web findet die Validierung statt. Der Certificate Request hat später für die Verwendung von SSL keine Bedeutung. Signed Certificate (mydomain-de.crt)Das signierte Zertifikat wird von Thawte nach Validierung geliefert und kann bei Strato unter "SSL-Verwaltung/Easy SSL" abgerufen werden. Das Zertifikat wird als mydomain-de.crt gespeichert. InstallationInstallation des Private Key und des Zertifikats auf dem Server: # mv mydomain-de.csr /etc/ssl/certs # mv mydomain-de.key /etc/ssl/private # chown root.root /etc/ssl/private # chmod 600 /etc/ssl/private Apache-Konfiguration: <IfModule mod_ssl.c>
<VirtualHost *:443>
...
SSLEngine on
SSLCertificateFile /etc/ssl/certs/mydomain-de.crt
SSLCertificateKeyFile /etc/ssl/private/mydomain-de.key
...
</VirtualHost>
</IfModule>
Donnerstag, 29. Dezember 2011STRATO HiDrive unter Linux nutzenInstallation von davfs (Debian): # apt-get install davfs2 Dateisystem manuell mounten: # mkdir /hidrive # mount -t davfs https://webdav.hidrive.strato.com /hidrive Username: myname Password: mypassword Eintrag zur fstab hinzufügen: # vi /etc/fstab ... https://webdav.hidrive.strato.com /hidrive davfs noauto,user 0 0 Dateisystem vereinfacht manuell mounten: # mount /hidrive Dateibaum DIR per rsync in HiDrive Nutzerverzeichnis übertragen, ohne Verwendung des Mountpoint: $ rsync -avz -e ssh DIR myname@rsync.hidrive.strato.com:/users/myname/ Unter "Einstellungen/Kontenverwaltung/OpenSSH-Schlüssel" kann der Public-Key des aufrufenden Benutzers hochgeladen werden, so dass sich die Passworteingabe vermeiden lässt. LinksHiDrive Login: https://hidrive.strato.com/ Mittwoch, 28. Dezember 2011Oracle+Linux: ORA-00845: MEMORY_TARGET not supported on this systemUnter Linux (Debian) bricht eine zuvor funktionierende Oracle-Datenbank beim Hochfahren plötzlich ab, mit der Meldung: ORA-00845: MEMORY_TARGET not supported on this system Im Netz wird in Blogs als Lösung genannt, man möge /dev/shm mounten # mount -t tmpfs tmpfs -o size=2g /dev/shm oder, falls /dev/shm bereits gemountet ist, den Speicher vergrößern # mount -o remount,size=2g /dev/shm Dies hat beides allerdings nicht geholfen, da die Fehlerursache eine andere war. Die Meldung im alert_<DB>.log zu dem Fehler lautet: WARNING: You are trying to use the MEMORY_TARGET feature. This feature requires the /dev/shm file system to be mounted for at least 1275068416 bytes. /dev/shm is either not mounted or is mounted with available space less than this size. Please fix this so that MEMORY_TARGET can work as expected. Current available is 0 and used is 0 bytes. Ensure that the mount point is /dev/shm for this directory. Der entscheidende Punkt in der Meldung, welcher zur Lösung führt, ist, dass Oracle keinen verfügbaren Speicher erkennt ("Current available is 0 and used is 0 bytes") und dass der Mountpoint exakt /dev/shm sein muss ("Ensure that the mount point is /dev/shm for this directory"). Letztere Bedingung war auf dem Debian-System (testing) nicht erfüllt: # df -h /dev/shm Filesystem Size Used Avail Use% Mounted on tmpfs 3.0G 0 3.0G 0% /run/shm Als Mountpoint wird hier nicht /dev/shm angezeigt, sondern /run/shm, weil /dev/shm lediglich ein Symlink auf /run/shm ist: # ls -l /dev/shm lrwxrwxrwx 1 root root 8 Aug 19 09:37 /dev/shm -> /run/shm Mit diesem Setup kommt der Oracle-Kernel (11.2.0.1.0) nicht klar. Er erkennt (aus nicht weiter erforschten Gründen) die Größe des Shared-Memory-Bereichs nicht. Der Fix besteht darin, im Oracle-Kernel alle Vorkommen von /dev/shm durch /run/shm zu ersetzen: # cd $ORACLE_HOME/bin # cp oracle oracle.bak # sed 's|/dev/shm|/run/shm|g' oracle.bak >oracle Danach fährt die Datenbank wieder hoch: $ sqlplus / as sysdba SQL*Plus: Release 11.2.0.1.0 Production on Fri Aug 19 13:29:21 2011 Copyright (c) 1982, 2009, Oracle. All rights reserved. Connected to an idle instance. SQL> startup ORACLE instance started. Total System Global Area 1272213504 bytes Fixed Size 1336260 bytes Variable Size 805309500 bytes Database Buffers 452984832 bytes Redo Buffers 12582912 bytes Database mounted. Database opened. Dienstag, 20. Dezember 2011Nexus S i9023 mit unvollständigem Android Release von AmazonAmazon Warehouse Deals hat mir einen Rückläufer des Google Phone Nexus S i9023 für ca. 70% des Neupreises verkauft. Das Smartphone wurde nach Angaben von Amazon auf Funktionsfähigkeit geprüft und für "gut" befunden.
Leider ist das Gerät unbrauchbar. Die rote Meldung auf dem Display, die einem nach dem Einschalten unübersehbar ins Auge sticht, deutet bereits darauf hin: WARNING!!! S/W is not completely installed. DOWNLOAD Full S/W Before Release. Eine genauere Prüfung ergibt, dass die Installation tatsächlich defekt ist. Es handelt sich anscheinend um eine Entwicklerversion des Smartphone, auf welcher unvollständig Android 2.4 installiert ist - eine Version, die es zum Zeitpunkt der Lieferung offiziell gar nicht gibt. Im Netz habe ich keine aktuelle, installierbare Android 2.3.6 Komplettversion gefunden (nur Updates von der vorherigen Version) und das Phone daher reklamiert und an Amazon zurückgeschickt. Dass das Gerät vor Auslieferung geprüft wurde, kann also nicht stimmen. Eine unerfreuliche Sache, die mich einige Stunden gekostet hat. Sonntag, 27. November 2011Cisco VPN-Verbindung (vpnclient) loggen/debuggenDie Ausgaben des Cisco vpnclient sind nicht unbedingt informativ, wenn etwas schief geht. Hier hilft die Aktivierung und Auswertung des Log. Das Logging wird in der Datei vpnclient.ini aktiviert. Hierzu wird die Option EnableLog=1 gesetzt und alle LogLevel-Einträge auf LogLevel=3. Das Logging wird gestartet durch $ ipseclog /tmp/vpnclient.log Die Logmeldungen werden nach /tmp/vpnclient.log geschrieben. Samstag, 26. November 2011Cisco vpnclient unter Linux Kernel 2.6.38+ProblemDas für frühere Kernel-Versionen kompilierte Kernel-Modul cisco_ipsec crasht bei Aufruf des Cisco vpnclient unter Linux 2.6.38. Das System ist danach nur noch eingeschränkt nutzbar. LösungDas Problem wurde auf http://forum.tuxx-home.at diskutiert und behoben. Der Patch dort funktioniert allerdings nicht, da der Patch, den man nur per Copy&Paste erhalten kann, in der Form defekt ist. Ich habe diesen händisch restauriert und aus den Patches
einen einzigen Patch erstellt, der auf das originale Cisco-Archiv angewendet werden kann. Installation vpnclient für Linux 2.6.38+
Links
Montag, 5. September 2011SQL: Doubletten findenSELECT col1, ..., colN, COUNT(*) FROM tab GROUP BY col1, ..., colN HAVING COUNT(*) > 1 col1, ..., colN sind die Kolumnen, über denen die Doubletten-Eigenschaft geprüft wird. Dienstag, 30. August 2011MySQL: Data Directory neu aufsetzen
MySQL: Mehrere Instanzen auf einem ServerEine elegante Möglichkeit, mehrere MySQL-Instanzen auf einem Server zu betreiben, bietet das Programm mysqld_multi. Es erweitert die Konfigurationsdatei /etc/my.cnf um Abschnitte für mehrere MySQL-Serverinstanzen [mysqld#] (wobei # die jeweilige Instanznummer bezeichnet). In den Abschnitten werden den Instanzen getrennte Datadirs, Sockets, Ports, Pid-Files usw. zugewiesen. mysqld_multi ist das Frontend-Programm zum Starten und Stoppen der einzelnen Instanzen, à la $ mysqld_multi start 2 Eine Beispielkonfiguration, die auf die eigenen Verhältnissse angepasst und in my.cnf eingesetzt werden kann, liefert das Kommando $ mysqld_multi --example Die ausführliche Doku ist auf der Manpage zu finden: $ man mysql_multi Montag, 29. August 2011Linksammlung: UTF-8 Portierung
MySQL
Perl
Mittwoch, 11. Mai 2011SVN: Auf Branch entwickelnErzeugen eines Branch$ svn copy svn://HOST:PORT/trunk svn://HOST:PORT/branches/BRANCH -m MSG HOST : Name des SVN Host PORT : Portnummer (falls der Server nicht auf dem Standardport 3690 läuft) BRANCH : Name des Branch, welcher frei gewählt werden kann MSG : Logmeldung zur Brancherzeugung $ svn up /DIR/branches/BRANCH DIR : Wurzelverzeichis des ausgecheckten Repository (Trunk+Branches) Aktualisieren des Branch$ cd /DIR/branches/BRANCH $ svn merge svn://HOST:PORT/trunk Das Aktualisieren des Branch mit den Änderungen im Trunk sollte so oft wie möglich passieren, damit nicht zu viele Konflikte auflaufen. Rückintegrieren des Branch$ cd /DIR/trunk $ svn merge --reintegrate svn://HOST:PORT/branches/BRANCH Löschen des Branch$ svn delete /DIR/branches/BRANCH Nach der Rückintegration des Branch in den Trunk ist der Branch nutzlos geworden und sollte gelöscht werden. Im Repository bleibt er vorhanden, es wird ohne Angabe der letzten Revision Number bei einem Update in /DIR/branches aber keine (unerwünschte) Working Copy mehr erzeugt. O'Reilly SVN BuchFreie Online-Version von Version Control with Subversion Freitag, 29. April 2011YouTube: Sperre verhindernWer sichergehen will, dass der selbstgemachte Videoclip wegen der Hintergrundmusik von YouTube nicht gesperrt oder mit Werbung versehen wird, kann versuchen, die Audio-Daten so zu verändern, dass die YouTube Content-Erkennung nicht anspricht. Ein Weg, dies zu erreichen, ist, die Geschwindigkeit des Audio-Materials vor dem Hinzufügen zum Clip zu verändern. Eine Geschwindigkeitserniedrigung oder -erhöhung im Bereich von 1 Prozent reicht schon aus. Eventuell muss mit verschiedenen Werten experimentiert werden. Diese Audio-Manipulation ist nicht unbedingt hörbar, hat aber in jedem Fall Auswirkungen auf das Timing innerhalb des Clip, weswegen man die Änderung vorab machen und austesten sollte (s.u. Test Audio-Datei). In audacity findet sich die Funktion unter dem Menüpunkt "Effect/Change Speed". Ein positiver Wert im Eingabefeld "Percent Change" erhöht die Abspielgeschwindigkeit, ein negativer Wert reduziert sie. Test Audio-DateiMit ffmpeg lässt sich aus einem einzelnen Bild (IMAGE) und einer Audio-Datei (AUDIO) ein Clip (VIDEO.mp4) erzeugen, der testweise nach YouTube hochgeladen werden kann. $ ffmpeg -loop_input -i IMAGE -i AUDIO -t SEC -ab 128kb VIDEO.mp4 -i IMAGE : Bild-Datei, z.B. 480x360 Pixel -i AUDIO : Audio-Datei -t SEC : Länge des generierten Clip in Sekunden, z.B. 60 für eine Minute -ab 128kb : Audio-Bitrate im generierten Clip, 128kb = CD-Qualität VIDEO.mp4 : generierter Clip ffmpeg: Lautstärke anheben oder verringernDie Audio-Lautstärke kann bei ffmpeg mit der Option -vol verändert werden. Diese Option ist auf der Manpage (Version 0.6.2) nicht dokumentiert. $ ffmpeg -i INPUT_FILE -vol N OUTPUT_FILE Der Lautstärke-Wert N ist eine Angabe in "Byte Percent", d.h. 256 = 100%. Mit dem Wert 512 wird die Lautstärke also verdoppelt und mit dem Wert 128 wird sie halbiert. Donnerstag, 28. April 2011Linksammlung Video und AudioVideo
AudioDonnerstag, 10. März 2011Oracle 11g unter Linux installierenEine Anleitung zum Installieren von Oracle 11g unter Debian, die versucht, mögliche Probleme von vornherein auszuschließen, dafür aber umfangreiche Vorarbeiten verlangt, findet sich hier: http://edin.no-ip.com/blog/hswong3i/oracle-database-11g-release-1-debian-sid-howto Meine Anleitung hat das Ziel, die Voraussetzungen für den Aufruf des Installers zu schaffen. Da der Installer selbst den Softwarestand und die Kernelparameter prüft, können Anpassungen auch bei laufender Installation vogenommen werden.
Schritt 1: DownloadDateien von Oracle.com herunterladen: Download 11g Enterprise Edition (Hierfür ist ein OTN-Konto nötig) Schritt 2: Oracle-Benutzer und DBA-Gruppe erzeugen# addgroup --system dba # adduser --system --home /opt/oracle --shell /bin/bash --ingroup dba \ --gecos 'Oracle DBA' oracle # passwd oracle Schritt 3: Dateien entpackenAuf Benutzer oracle wechseln, unter dessen Rechten wird die weitere Installation durchgeführt: # su - oracle $ unzip linux_11gR2_database_1of2.zip $ unzip linux_11gR2_database_2of2.zip Die Dateien werden von unzip in ein Unterverzeichnis database entpackt. Wo entpackt wird, ist egal. Die entpackten Dateien werden nur während der Installation gebraucht. Nach der Installtion kann das gesamte Verzeichnis gelöscht werden. Schritt 4: Installer ausführenWichtig: Wurde der Desktop unter einem anderen Benutzer als oracle gestartet, muss der Benutzer den Desktop für den Zugriff des Benutzers oracle freigeben, da dieser den Installer aufruft. Geschieht die Freigabe nicht, stirbt der Installer nach einigen Sekunden mit der wenig aussagekräftigen Fehlermeldung No protocol specified [Java Stacktrace] Die Freigabe erfolgt mit dem Kommando: <user>$ xhost + Als Benutzer oracle ausführen: $ cd database $ ./runInstaller Der Installer führt den Benutzer durch die Installation, nimmt zahlreiche Prüfungen vor und schreibt ein Logfile, das bei Problemen konsultiert werden kann. Unstimmigkeiten können parallel behoben werden, Prüfungen und fehlgeschlagene Schritte können immer wieder neu durchgeführt werden bis es klappt.
Installierte DateienKonfigurationsdateien in /etc/etc/oraInst.loc /etc/oratab Die eigentliche Installation/opt/oracle/app/* Hilfsprogramme/usr/local/bin/oraenv /usr/local/bin/coraenv /usr/local/bin/dbhome Datenbank-Dateien/var/opt/oracle/<DATABASE>/* Freitag, 28. Januar 2011mod_perl: Virtual Host mit eigenem Perl-InterpreterPer Default wird bei mod_perl derselbe Perl-Interpreter für alle Virtual Hosts genutzt. Das kann zu Problemen führen, wenn die Applikationen unterschiedliche Versionen derselben Module nutzen. Dies kann bei mod_perl 2.0 mit der PerlOption +Clone ausgeschlossen werden: <VirtualHost ...> PerlOptions +Clone </VirtualHost> Die Option +Clone bewirkt, dass für den betreffenden Virtual Host ein eigener Interpreter-Pool genutzt wird. Dieser entsteht durch Klonen des Parent-Interpreters (welcher eventuell schon eine Startup-Initialisierung erfahren hat). Ein Interpreter-Pool mit einem gänzlich neuen Parent-Interpreter wird bei Angabe von +Parent erzeugt: <VirtualHost ...> PerlOptions +Parent </VirtualHost> Um dem Interpreter einen (oder mehrere) eigene Suchpfade mitzugeben, kann die Perl Standard-Option -I verwendet werden: PerlSwitches -I/var/www1/modules Freitag, 14. Januar 2011Finde Dateinamen mit SonderzeichenFinde in Dateibaum DIR alle Dateinamen mit Sonderzeichen, also mit Zeichen, die nicht im ASCII-Zeichensatz liegen: find DIR | perl -ne "print if /[^[:ascii:]]/" Umlaute und andere Non-ASCII-Zeichen in Dateinamen sind problematisch und sollten vermieden werden, wenn nicht garantiert ist, dass systemweit mit ein und demselben Encoding gearbeitet wird, denn das Encoding eines Dateinamens lässt sich aus diesem normalerweise nicht herleiten. Dienstag, 4. Januar 2011Seamonkey installieren (Unix)Installation
Icon auf GNOME Panel legenMit der rechten Maustaste das Panel-Menü öffnen, "Add to panel" auswählen und einen "Custom Application Launcher" für das Executable anlegen. Das Seamonkey-Icon findet sich unter seamonkey/<VERSION>/chrome/icons/default/default.png Montag, 27. Dezember 2010FONIC: Klingelzeit verlängern, Kontostand abfragen etc.Bedingte Rufweiterleitung + Klingelzeit setzen**004*333**30#<abheben>
** Definieren
004* Umleitung bei Abwesenheit, Unerreichbarkeit, besetzt
333 Nummer, auf die umgeleitet wird (hier: FONIC-Mailbox)
** Dienstkennung (leer)
30 Zeitspanne in Sekunden (5 bis 30 möglich)
# Endekennung des GSM-Befehls
<abheben> GSM-Code an Provider übermitteln
Antwort:
Rufweiterleitung
Registrierung war erfolgreich
Bei Abwesenheit, Unerreichbarkeit (kein Netz oder Telefon ist ausgeschaltet) oder besetzt wird der Anrufer auf die FONIC-Mailbox weitergeleitet. Bei Abwesenheit klingelt das Telefon bis zur Weiterleitung die maximal möglichen 30 Sekunden. Bedingte Rufweiterleitung löschen##004#<abheben> Antwort: Rufweiterleitung Löschvorgang erfolgreich Alle bedingten Rufweiterleitungen (Abwesenheit, Unerreichbarkeit, besetzt) werden gelöscht. Die Mailbox geht anschließend nicht mehr ran. Der Anrufer hört eine Ansage des Providers, kann aber keine Nachricht hinterlassen. Kontostand abfragen*101#<abheben> Antwort: Ihr FONIC Guthaben beträgt: <X> EUR Tipp: Laden Sie Ihr Guthaben bequem und einfach vom Bankkonto auf. Infos unter www.fonic.de IMEI ermitteln*#06# Antwort (des Telefons): TTTTTTTTSSSSSSC TTTTTTTT Type Approval Code SSSSSS Seriennummer C Prüfziffer Die IMEI identifiziert das Telefon eindeutig. Im Falle eines Garantiefalls oder Diebstahls kann es notwendig bzw. vorteilhaft sein sie zu wissen. Genauere Information: http://de.wikipedia.org/wiki/IMEI Links
Montag, 6. Dezember 2010scp: Whitespace in Remote-DateinamenUm per scp Dateien, die Whitespace im Dateienamen enthalten, von einem enterfenten System zu kopieren, müssen die Leerzeichen zwei Mal maskiert werden, einmal für die lokale Shell und einmal für die remote Shell: $ scp 'user@host:/pfad/"eine datei"' . Freitag, 3. Dezember 2010DVD-Chapter rippenListe der verfügbaren Titel$ HandBrakeCLI --input=/dev/dvd --title=0 2>&1 | grep '\+'
[...]
+ title 3:
+ vts 1, ttn 3, cells 0->1 (150271 blocks)
+ duration: 00:14:27
+ size: 720x576, pixel aspect: 64/45, display aspect: 1.78, 25.000 fps
+ autocrop: 40/30/4/4
+ chapters:
+ 1: cells 0->0, 150266 blocks, duration 00:14:27
+ 2: cells 1->1, 5 blocks, duration 00:00:00
+ audio tracks:
+ 1, Deutsch (AC3) (2.0 ch) (iso639-2: deu), 48000Hz, 224000bps
+ subtitle tracks:
[...]
Chapter rippen$ HandBrakeCLI --input=/dev/dvd --title=<n> --chapters=<k>[-<j>] \
--deinterlace --output=<name>.<ext>
Weitere nützliche Optionen
Donnerstag, 4. November 2010MySQL: Bessere Antwortzeiten durch bessere Query-PläneDer MySQL Query Optimizer kann bessere Query-Pläne generieren, wenn er Informationen über die Tabelleninhalte hat. Diese können per SQL mit ANALYZE TABLE erzeugt werden oder - einfacher - mit dem Kommandozeilenprogramm mysqlcheck. Die Option zum Analysieren heißt --analyze. Bei Angabe der Option --all-databases werden alle Tabellen aller Schemata (in MySQL-Sprechweise: Datenbanken) auf einen Schlag analysiert. Das ist meistens das, was man will. $ mysqlcheck --analyze --all-databases ... bzw. in Kurzform $ mysqlcheck -a -A ... Mittwoch, 3. November 2010MySQL: Remote-Zugriff einrichtenDamit der MySQL-Server mysqld TCP-Verbindungen annimmt, muss ihm in my.cnf im Abschnitt [mysqld] eine Bind-Adresse zugewiesen werden: bind-address = <server-ip> Falls vorhanden, muss die Direktive skip-networking gleichzeitig auskommentiert werden, da diese Priorität hat und forciert, dass der Server nur Unix Domain Sockets zulässt. Per SQL einen neuen User anlegen und ihm den Remote-Zugriff von allen Hosts ('%') auf alle Schemata und Tabellen (*.*) erlauben: CREATE USER <user> IDENTIFIED BY '<password>'; GRANT ALL ON *.* TO '<user>'@'%'; Login mit mysql-Client: $ mysql -u <user> -h <host> --password=<password> Die User-Zugriffsberechtigungen stehen in der Tabelle mysql.user. Diese Tabelle kann mit INSERT/UPDATE/DELETE Statements auch direkt manipuliert werden. Montag, 1. November 2010FFmpeg OperationenAbschnitt extrahieren$ ffmpeg -i INFILE -ss 0:0:12.200 -t 0:0:5 ... OUTFILE -ss 0:0:12.200 : Start bei 12 Sekunden und 200 Millisekunden -t 0:0:5 : Länge 5 Sekunden (kann auch als -t 5 angegeben werden) Es ist wichtig, dass der Zeit-Offset -ss 0:0:12.200 als Parameter der Ausgabedatei angegeben wird, und nicht als Parameter der Eingabedatei, da sonst Keyframe-Probleme auftreten können. Film skalierenÄndere die Größe eines Films in WIDTHxHEIGHT: $ ffmpeg -i INFILE -s WIDTHxHEIGHT ... OUTFILE -s WIDTHxHEIGHT : die neue Breite und Höhe des Films Die Option -s ist nur sinnvoll, wenn das Seitenverhältnis gleich bleibt. Ansonsten wird das Bild verzerrt. Bei abweichendem Seitenverhältnis kann mit den Operationen pad oder crop gearbeitet werden (siehe pad und crop). Film bei Wiedergabe skalieren$ ffplay -vf scale=WIDTH:HEIGHT INFILE Film mit Balken versehen (pad)INFILE sei ein 16:9-formatiger Film der Größe 640x360, der mit 60 Pixel hohen Balken oben und unten auf 4:3-Format gebracht werden soll. Kommando: $ ffmpeg -i INFILE -vf pad=640:480:0:60 ... OUTFILE pad : Operation: Auffüllen 640:480 : die Größe (Dimension) WIDTH:HEIGHT des Resultats (OUTFILE) 0:60 : der Offset X:Y des Films von der oberen linken Ecke des Resultats Bildausschnitt extrahieren (crop)Mit folgendem Kommando werden die Balken wieder entfernt. $ ffmpeg -i INFILE -vf crop=640:360:0:60 ... OUTFILE
crop : Operation: Ausschneiden
640:360 : die Größe (Dimension) WIDTH:HEIGHT des Resultats
0:60 : der Offset X:Y des Ausschnitts von der oberen linken Ecke
des Eingangsmaterials (INFILE)
Audio nach MP3 wandeln$ ffmpeg -i INFILE -ab 128k -acodec libmp3lame -ac 2 ... OUTFILE -ab 128k : Audio-Bitrate in kb/s -acodec libmp3lame : MP3 Codec -ac 2 : Zwei Kanäle (stereo) Audio entfernen$ ffmpeg -i INFILE -an ... OUTFILE Bitrate, Framerate und Bildgröße eines HD-Films reduzieren$ ffmpeg -i INFILE -b 5000k -r 25 -s 1280x720 ... OUTFILE -b 5000k : Video-Bitrate auf 5000 kb/s reduzieren -r 25 : Frame-Rate auf 25 Bilder pro Sekunde reduzieren -s 1280x720 : Bildauflösung auf 1280x720 Pixel reduzieren Donnerstag, 28. Oktober 2010Cookies per JavaScript setzenServerseitig via HTMLWenn serverseitig kein Zugriff auf die Header der HTTP-Antwort besteht, kann ein Cookie auch per HTML gesetzt werden:
Zustand eines Select-Menü (per CGI.pm generiert) sichernEin onchange-Handler setzt einen Cookie, der den Zustand eines Select-Menü anwendungsglobal speichert (Perl/CGI.pm):
ROWNUM unter MySQLOracle kennt die Pseudo-Kolumne ROWNUM, die die Datensätze einer Selektion von 1 an aufsteigend durchnummeriert. In MySQL existiert dieses Konzept nicht, es kann aber mittels einer Benutzer-definierten Variable simuliert werden. Implementierung:
Einschränkung: Die Lösung ist unzureichend, wenn ein ORDER BY verwendet wird, da die Nummerierung vor der Sortierung stattfindet. Unter Oracle wird ROWNUM auch benutzt, um die Ergebnismenge auf die die ersten n Datensätze zu begrenzen. Dafür hat MySQL ein besseres Konzept, die SELECT-Klausel LIMIT. Javascript: HTML-Formular abbrechenEin HTML-Formular soll mittels Abbruch-Button beendet werden. Der Button schickt die Formulardaten nicht ab, sondern verzweigt auf irgendeine Seite URL, z.B. die Seite, von der aus das Formular aufgerufen wurde. Implementierung: <input type="button" value="Abbrechen" onclick="location.href = 'URL'">
Donnerstag, 21. Oktober 2010Perl: Apache2::Reload installierenApache2::Reload ist ein Perl-Modul, das Module einer mod_perl-Applikation automatisch neu lädt, wenn diese geändert wurden. Andernfalls müsste der HTTP-Server neu gestartet werden um die Änderungen sichtbar zu machen, was während der Entwicklung umständlich und zeitaufwändig ist.
Montag, 31. Mai 2010CSS: Listen portabel einrückenDie Browser benutzen unterschiedliche Wege, Listen einzurücken. Einige rücken per Padding ein, andere per Margin. Soll die Einrückung portabel verändert werden, müssen margin-left uns padding-left also zusammen gesetzt werden, und zwar eine Angabe auf die gewünschte Einrückung und die andere auf 0.
oder
Sonntag, 30. Mai 2010HTML-Konstrukte mit CSS gestaltenProblemEin aus mehreren Elementen bestehendes HTML-Konstrukt soll in seinem Aussehen frei gestaltbar sein. Wie lässt sich dies mit CSS erreichen? BeispielGegeben sei ein Inhaltsverzeichnis, bestehend aus einer Überschrift (h1) und verschachtelten Listen (ul, li) mit Links (a) auf die Dokument-Abschnitte.
Der HTML-Code wird ohne CSS vom Browser (Firefox) ungefähr so dargestellt (die Strukturelemente für den Titel (h1) und die Listen (ul) sind zur Verdeutlichung grau hinterlegt):
LösungUm ein HTML-Konstrukt aus mehreren Elementen per CSS anpassbar zu machen, gehen wir folgendermaßen vor:
Dienstag, 25. Mai 2010dvgrab: Video von miniDV-Camcorder lesenMit dvgrab wird ein Video von einem digitalen Camcorder über FireWire gelesen und in Form von einzelnen Clips (.dv-Dateien) auf die Platte geschrieben. Die von mir bevorzugt verwendete Kommandozeile lautet: $ dvgrab -autosplit -size 0 -timestamp clip- -autosplit : trenne den Video-Strom auf Clip-Grenzen -size 0 : erlaube, dass Clip-Dateien beliebig groß werden können -timestamp : füge den Timecode des ersten Frame zum Clip-Grundnamen hinzu clip- : Grundname der Clip-Dateien Die Clip-Dateien erhalten die Namen clip-YYYY.MM.DD_HH-MI-SS.dv. Pro Sekunde fallen 3.43 MB an Daten an, eine Stunde Videomaterial belegt 12.35 GB Plattenplatz. Donnerstag, 20. Mai 2010Perl: POD als Programm-HilfetextDas Core-Modul Pod::Usage kann einen Programm-Hilfetext aus der eingebetteten POD-Dokumentation generieren. Es geht auch einfacher:
produziert auf STDOUT NAME
myprog - a simple program
LICENSE
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
Mittwoch, 19. Mai 2010Medion Life S60003 MP3 Player unter DebianDer Medion Life S60003 ist ein einfacher Player zum Abspielen von MP3- und WMA-Dateien. Zum Datenaustausch wird dieser auf einen freien USB-Port gesteckt. Der Player wechselt in den Zustand "USB Connected". Wird gerade ein Titel gespielt, muss die Wiedergabe erst angehalten werden. Zugriff auf das Dateisystem des PlayersDer Player wird von udev erkannt und vom System automatisch auf ein Verzeichnis unter /media gemountet. Der Vorgang wird in /var/log/messages protokolliert: usb 3-1: new high speed USB device using ehci_hcd and address 18 usb 3-1: New USB device found, idVendor=066f, idProduct=8588 usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=5 usb 3-1: Product: MD 83366 usb 3-1: Manufacturer: Medion usb 3-1: SerialNumber: 43F9000056B398A30002D8F515A958A3 usb 3-1: configuration #1 chosen from 1 choice scsi18 : SCSI emulation for USB Mass Storage devices scsi 18:0:0:0: Direct-Access Medion MD 83366 0100 PQ: 0 ANSI: 4 scsi 18:0:0:1: Direct-Access Medion MD 83366 0100 PQ: 0 ANSI: 4 sd 18:0:0:0: [sdc] 478976 4096-byte logical blocks: (1.96 GB/1.82 GiB) sd 18:0:0:0: [sdc] Write Protect is off sd 18:0:0:0: [sdc] 478976 4096-byte logical blocks: (1.96 GB/1.82 GiB) sd 18:0:0:1: [sdd] Attached SCSI removable disk sdc: sd 18:0:0:0: [sdc] 478976 4096-byte logical blocks: (1.96 GB/1.82 GiB) sd 18:0:0:0: [sdc] Attached SCSI removable disk Der Mountpoint lässt sich mit mount(1) herausfinden: $ mount ... /dev/sdc on /media/87C9-FFD0 type vfat (rw,nosuid,nodev,uhelper=udisks, uid=1000,gid=1000,shortname=mixed,dmask=0077,utf8=1,flush) Eigentlich ist der Flash-Speicher des Players nicht direkt mountbar. Vielmehr wird der Player als MTP-Gerät (http://de.wikipedia.org/wiki/Media_Transfer_Protocol) angesprochen. Der Eintrag in /lib/udev/rules.d/45-libmtp8.rules lautet: # Medion MD8333
ATTR{idVendor}=="066f", ATTR{idProduct}=="8588", SYMLINK+="libmtp-%k",
MODE="660", GROUP="audio"
Der Player kann, wenn obiges Setup stimmt, auch per Hand gemountet werden: # mount /dev/sdX /mnt X ist der Buchstabe des SCSI-Geräts ohne eine Partitionsnummer, hier: /dev/sdc. Ist unter System/Preferences/File Management/Media (Gnome) die Option "Browse Media when inserted" aktiviert, wird von Gnome der File Browser Nautilus auf dem Verzeichnis gestartet, wenn es automatisch gemountet wird. Aber ACHTUNG: Dies alles klappt nicht, wenn der Gnome Audio-Player Rhythmbox läuft! Dieser nimmt selbst mit dem Player via MTP Kontakt auf. Offenbar kann der Player nicht gleichzeitig gemountet sein, d.h. ein etwaiger Mount - egal ob automatisch oder manuell aufgebaut - wird sofort wieder abgebaut oder anderweitig gestört. Dateien übertragenGemountet kann der Player als Datenträger für beliebige Dateien und Verzeichnisstrukturen verwendet werden. Auch die Musiksammlung kann theoretisch mittels Dateisystem-Operationen auf dem Player verwaltet werden. Dies ist allerdings nicht praktikabel, da der Player die in den MP3-Dateien enthaltenen ID3-Tags nicht auswertet. Werden MP3-Dateien einfach nur kopiert, befinden sie sich anschließend zwar auf dem Player und können gespielt werden, aber der Player "weiß" nichts über ihren Inhalt und kann dem Benutzer die zur Unterscheidung wichtigen Informationen Titel, Künstler, Album, Jahr, Genre nicht präsentieren. Daher ist es besser, die Dateien mit Rhythmbox - oder einem anderen Programm, welches Musikdateien per MTP verwaltet - zu übertragen. Der Player erhält dann auch die Meta-Information zu den Dateien. Donnerstag, 25. März 2010Perl: Plus / Minus UnendlichPerl kennt mehrere Zeichenketten, die - numerisch interpretiert - plus und minus Unendlich bedeuten.
Beispiel: Maximum ermitteln
Aber Achtung: Diese besonderen Werte sind nicht sonderlich gut dokumentiert und scheinen bei einigen Windows-Ports nicht zu funktionieren. Siehe: http://reneeb-perlblog.blogspot.com/2010/03/unendliches-perl.html Donnerstag, 18. März 2010Perl: Dirhandles objektorientiertAnalog zu lexikalischen Filehandles besitzt Perl lexikalische Dirhandles. Eine Dirhandle ist ein Iterator über einem Verzeichnis. Die Operationen auf Dirhandles lassen sich objektorientiert kapseln. Hier eine entsprechende Klasse Dirhandle mit drei Methoden: new() (Directory öffnen), close() (Directory schließen) und next() (nächster Directory-Eintrag): Beispiel: Gib alle Einträge des Verzeichnisses $dir auf STDOUT aus 1 use Dirhandle; 2 3 my $dh = Dirhandle->new($dir); 4 while (my $entry = $dh->next) { 5 say $entry; 6 } 7 $dh->close; Das Dirhandle-Objekt $dh kann wie jede normale Dirhandle an die Perl-Builtins readdir(), telldir(), seekdir(), rewinddir(), closedir() übergeben werden. Dienstag, 16. März 2010Perl: Filehandles objektorientiertMit lexikalischen Filehandles ist es in Perl leicht möglich, File-I/O objektorientiert zu kapseln. Hier zur Veranschaulichung eine Klasse Filehandle mit drei Methoden: new() (Datei öffnen), close() (Datei schließen) und slurp() (Datei komplett einlesen): Beispiel: Lies eine Datei komplett ein und gib sie auf STDOUT aus 1 use Filehandle; 2 3 my $fh = Filehandle->new('<',$file); 4 print $fh->slurp; 5 $fh->close; Der Clou: Die Filehandle $fh kann unabhängig von der Klasse wie jede andere Perl-Filehandle benutzt werden, z.B. mit dem Diamant-Operator <> oder jeder anderen Filehandle-Operation wie read(), write() usw. Obiges Programm lässt sich also auch so implementieren: 1 use Filehandle; 2 3 my $fh = Filehandle->new('<',$file); 4 while (<$fh>) { 5 print; 6 } 7 $fh->close; Freitag, 5. März 2010Perl: Crash bei Umleitung von STDERR auf Skalare VariableIch weiß nicht, wann Perl mir mal abgestürzt ist, aber jetzt bin ich auf einen Fall gestoßen:
$ ./test.pl Segmentation fault Perl-Version (andere habe ich nicht probiert): $ perl -v This is perl, v5.10.1 (*) built for i686-linux VariationenWenn $s kein In-Memory File ist, geht es. Bei $s =~ s/./xx/; geht es (ohne g Modifier). Bei $s =~ s/./x/g; geht es (der String wird nicht länger). Schließen von STDERR vor dem s/// ändert nichts. Dienstag, 9. Februar 2010GNU Makefile zum Konvertieren von DateienMitunter soll eine Menge von Dateien, die man erstellt und bearbeitet, systematisch in etwas anderes, z.B. ein anderes Format, konvertiert werden. Die Konvertierung lässt sich mit dem Utilty make organisieren, so dass überflüssige Konvertierungen vermieden werden. Wie sieht ein GNU Makefile für diese Aufgabe aus? Das folgende (fiktive) Beispiel geht davon aus, dass wir .in-Dateien in .out-Dateien konvertieren wollen. Die Konvertierung übernimmt das (fiktive) Programm in2out.
Montag, 8. Februar 2010Syntax-Highlighting mit highlightHighlight stellt die Syntax von zahlreichen Programmiersprachen farbig und mit Fontattributen wie kursiv und fett dar: $ highlight --syntax=LANG --fragment <CODE >CODE.html Die Option --syntax=LANG stellt die Programmiersprache ein, --fragment sorgt dafür, dass keine vollständige HTML-Seite, sondern einbettbarer HTML-Code generiert wird. Die zugehörigen CSS-Klassen liefert folgendes Kommando nach stdout: $ highlight --print-style --style-outfile=stdout | grep '^\.' >CODE.css Das nachgeschaltete grep sorgt dafür, dass der Output auf die relevanten Klassen für eine Einbettung eingeschränkt wird. Freitag, 5. Februar 2010Syntax-Highlighting mit perltidyPerltidy stellt die Syntax von Perl-Code farbig und mit Fontattributen wie kursiv und fett dar, wenn man den Code mit Option -html nach HTML wandelt. Ich nutze dieses Feature, um lesbareren Perl-Code für mein Blog zu generieren. Für die Einbettung des generierten HTML-Codes in eigene HTML-Seiten sind allerdings kleinere Sonderbehandlungen nötig. Anpassung der Stylesheet-DefinitionenPerltidy generiert mit $ perltidy -html -ss >FILE.css eine Stylesheet-Datei, die die Definitionen der CSS-Klassen für die Syntaxelemente enthält und in die eigenen HTML-Seiten eingebunden werden kann: /* default style sheet generated by perltidy */ body {background: #FFFFFF; color: #000000} pre { color: #000000; background: #FFFFFF; font-family: courier; } .c { color: #228B22;} /* comment */ .cm { color: #000000;} /* comma */ .co { color: #000000;} /* colon */ .h { color: #CD5555; font-weight:bold;} /* here-doc-target */ .hh { color: #CD5555; font-style:italic;} /* here-doc-text */ .i { color: #00688B;} /* identifier */ .j { color: #CD5555; font-weight:bold;} /* label */ .k { color: #8B008B; font-weight:bold;} /* keyword */ .m { color: #FF0000; font-weight:bold;} /* subroutine */ .n { color: #B452CD;} /* numeric */ .p { color: #000000;} /* paren */ .pd { color: #228B22; font-style:italic;} /* pod-text */ .pu { color: #000000;} /* punctuation */ .q { color: #CD5555;} /* quote */ .s { color: #000000;} /* structure */ .sc { color: #000000;} /* semicolon */ .v { color: #B452CD;} /* v-string */ .w { color: #000000;} /* bareword */ Anpassung 1Die CSS-Definitionen für <body> und <pre> am Anfang sollten im Falle einer Einbettung nicht vorkommen, da diese an anderer Stelle definiert sind. Sie lassen sich mit grep wegfiltern. $ perltidy -html -ss | grep '^\.' Anpassung 2Die Namen der CSS-Klassen bestehen aus ein oder zwei Buchstaben, was zu Nameclashes führen kann. Dies verbessere ich, indem ich dem Klassennamen einen Präfix voranstelle. Ich wähle "pt-". $ perltidy -html -ss | grep '^\.' | sed -e 's/^\./.pt-/' Resultierende CSS-Datei.pt-c { color: #228B22;} /* comment */ .pt-cm { color: #000000;} /* comma */ .pt-co { color: #000000;} /* colon */ .pt-h { color: #CD5555; font-weight:bold;} /* here-doc-target */ .pt-hh { color: #CD5555; font-style:italic;} /* here-doc-text */ .pt-i { color: #00688B;} /* identifier */ .pt-j { color: #CD5555; font-weight:bold;} /* label */ .pt-k { color: #8B008B; font-weight:bold;} /* keyword */ .pt-m { color: #FF0000; font-weight:bold;} /* subroutine */ .pt-n { color: #B452CD;} /* numeric */ .pt-p { color: #000000;} /* paren */ .pt-pd { color: #228B22; font-style:italic;} /* pod-text */ .pt-pu { color: #000000;} /* punctuation */ .pt-q { color: #CD5555;} /* quote */ .pt-s { color: #000000;} /* structure */ .pt-sc { color: #000000;} /* semicolon */ .pt-v { color: #B452CD;} /* v-string */ .pt-w { color: #000000;} /* bareword */ Anpassung des HTML-CodesPerltidy erzeugt mit $ perltidy -html -pre <FILE >FILE.html eine Quelltext-Darstellung in HTML. Diese kann in die eigene Seite eingebunden werden. Anpassung 1Der HTML-Code ist in ein <pre> ohne Klassenanabe eingefasst. Das CSS-Layout dieses <pre> lässt sich also nicht gezielt anpassen. Am besten filtert man es weg und setzt den HTML-Code in ein eigenes <pre>. $ perltidy -html -pre <FILE | egrep -v '^</?pre>' Anpassung 2Die CSS-Klassennamen müssen an die oben gewählten Namen in der Stylesheet-Datei angepasst werden. $ perltidy -html -pre | egrep -v '^</?pre>' | sed -e 's/class="/class="pt-/g' Resultierender HTML-CodeAus print "Hello world!\n"; wird im HTML-Output (Umbruch hinzugefügt) <span class="pt-k">print</span> <span class="pt-q"> "Hello world!\n"</span><span class="pt-sc">;</span> und im Browser print "Hello world!\n"; Perl: Effizient Zeichen zählenIst eine FAQ (s. perldoc -q occurrences), aber ich vergesse immer die genaue Syntax, da ich tr/// selten nutze und es mehrere Funktionen in sich vereint: $n = $str =~ tr/\n//; $n ist in diesem Fall die Anzahl der Zeilenumbrüche in $str. Mittwoch, 3. Februar 2010Apache: Redirection auf SubdirectoryMit der Direktive Redirect kann ein Seitenzugriff auf eine andere Seite umgeleitet werden. Die Umleitung schließt alle Subpfade ein, also Seiten mit gleichem Pfadanfang. Möchte man ein Directory auf ein Subdirectory umleiten, klappt dies mit Redirect nicht, weil das zu einer Endlos-Rekursion führt. Die Redirect-Regel Redirect /a /a/b führt bei Aufruf von /a zu der endlosen Kette von HTTP-Aufrufen /a /a/b /a/b/b /a/b/b/b ... bis der Browser dies erkennt und mit einer Meldung wie Redirect Loop: Redirection limit for this URL exceeded. abbricht. Die Lösung liefert die (leistungsfähigere) Direktive RedirectMatch. Mit dieser lässt sich der umzulenkende Pfad per Regex präzise eingrenzen: RedirectMatch /a$ /a/b Das Dollarzeichen verankert den Pfad /a am Ende des URL, so dass Subpfade nicht mehr matchen und die Rekursion unterbleibt. Da durch die Regel keine Subpfade weitergeleitet werden, müssen die Zugriffe innerhalb von /a/b relativ sein. Ist das Ausgangsdirectory das Root-Directory, muss auch der Anfang verankert werden, da jedes Verzeichnis auf / endet: RedirectMatch ^/$ /a Freitag, 29. Januar 2010Rsync: Abweichende Rechte einstellenMit der Option -a führt rsync den Abgleich im Archive Mode durch, d.h. Symlinks, Devices, Permissions, Ownerschaft usw. werden auf die Zielmaschine transferiert. Was aber, wenn gewisse Unterschiede erforderlich sind, z.B. die Ownerschaft einiger Dateien verschieden sein muss, weil der Owner oder die Group auf der Zielmaschine anders heißen? Beispiel: Die Group des HTTP-Servers heißt auf der einen Maschine www-data während sie auf der anderen Maschine apache heißt. Über die Group bekommt der HTTP-Server Rechte auf bestimmten Dateien eingeräumt, sie muss also passend zur Maschine gesetzt sein. Solche Differenzen kann rsync nicht auflösen und bietet auch keine Option hierfür. Es lässt sich aber mit einem nachgeschalteten Shell-Skript erreichen, das via ssh auf der Zielmaschine ausgeführt wird: rsync -az --delete -e ssh DIR1/ USER@HOST:DIR2 ssh USER@HOST CMD Wird CMD in DIR1 abgelegt, wird es durch den rsync-Aufruf mit verwaltet, also automatisch auf dem neusten Stand gehalten. Donnerstag, 28. Januar 2010Overlays in Google Earth einbindenOverlays sind Bilder, die von Google Earth auf einen Bereich der Erdoberfläche (GroundOverlays) oder statisch ins Anwendungsfenster (ScreenOverlays) projeziert werden. Zu den Bildern gehört eine Spezifikation in KML (Keyhole Markup Language), die die Bilder beschreibt und festlegt, wie Google Earth mit ihnen verfahren soll. KML ist XML-basiert und wird in einer Datei mit der Extension .kml gespeichert. Die kml-Datei und die Bild-Dateien können zusammen in Form einer einzelnen kmz-Datei an Google Earth übergeben werden. Die kmz-Datei ist eine ZIP-Datei, die die genannten Dateien enthält. Die kmz-Datei wird entweder über "File/Open" geladen oder als Parameter beim Aufruf von Google Earth angegeben. Beispiel
KML-Datei
Obige KML-Spezifiktion beschreibt ein Bild, das auf die Erdoberfläche projeziert wird (Element GroundOverlay) und ein Bild, das statisch in der oberen linken Ecke des Fensters dargestellt wird (Element ScreenOverlay). Die beteiligten Hauptelemente sind: Document, GroundOverlay, ScreenOverlay. Für die Platzhalter __NAME__, __DESCRIPTION__ usw. müssen konkrete Werte eingesetzt werden.
MIME TypeWird die kmz-Datei von einem HTTP-Server ausgeliefert, sollte dieser den MIME-Type kennen: application/vnd.google-earth.kmz kmz Im Browser kann Google-Earth als Helper-Applikation vereinbart werden. Beim Eintreffen einer kmz-Datei wird Google Earth dann automatisch gestartet und positioniert an den betreffenden Ort. Die Angaben für den Browser sind:
ApplikationMittwoch, 27. Januar 2010Perl: Gleitkomma-Zahlen ausgeben wie sie sindVielleicht trivial, aber mir war die Antwort bislang nicht klar: Wie gebe ich eine Gleitkomma-Zahl aus, ohne dass Stellen wegfallen oder überflüssige Nullen am Ende erscheinen? Bei der Ausgabe von Gleitkommazahlen habe ich bislang automatisch zu printf/sprintf und %f gegriffen, aber das Format-Element %f formatiert die Zahlen ja immer auf eine feste Anzahl an Stellen und rundet auf die letzte Stelle. Z.B. my $x = 0.123456789; printf "%f",$x; ergibt 0.123457 (%f formatiert/rundet per Default auf 6 Nachkommastellen) Natürlich kann ich die Anzahl der Stellen groß wählen, aber dann bekomme ich u.U. zusätzliche Stellen, wenn die betreffende Zahl binär nur näherungsweise dargestellt werden kann: my $x = 0.123456789; printf "%.20f",$x; ergibt 0.12345678899999999734 Andererseits erhalte ich am Ende überflüssige Nullen bei Zahlen, die dezimal weniger als die vorgegebenen Stellen besitzen: my $x = 0.5; printf "%.20f",$x; ergibt 0.50000000000000000000 Was tun? Die Lösung ist (anscheinend) einfach: Ich gebe die Zahl nicht als Zahl sondern als String aus! D.h. im Falle von printf/sprintf mit Format-Element %s! Damit erhalte ich, was ich will. Die Zahl mit allen Stellen und nicht mehr my $x = 0.123456789; printf "%s",$x; 0.123456789 und ohne überflüssige Nullen my $x = 0.5; printf "%s",$x; 0.5 Bei näherer Überlegung leuchtet das ein, da Perl intern neben der (binären) numerischen Repräsentation eine Stringrepräsentation des Werts speichert, welche anfänglich genau der Zeichenfolge bei der Zuweisung entspricht. Schlussfolgerung: Programme, die nicht rechnen, sondern Gleitkommazahlen nur einlesen und wieder ausgeben, sollten, um Verfälschungen auszuschließen, diese bei der Ausgabe grundsätzlich als Strings und nicht als Zahlen behandeln. Dienstag, 26. Januar 2010Email-Adressen in HTML vor Spammern schützenIn Mailto-URLsStatt den Mailto-URL per href zu setzen, wird der mailto-URL zum Zeitpunkt des Klicks via JavaScript generiert. Nicht gut:
<a href="mailto:rudi.ratlos@host.dom">...</a>
Besser:
<a href="#" onclick="this.href = 'mailto:rudi.ratlos'+'@'+'host.dom'">...<a/>
Dies setzt natürlich JavaScript voraus. Aber schreibt heutzutage noch jemand Web-Anwendungen ohne JavaScript? Im Text
Statt die Email-Adresse im Klartext hinzuschreiben, wird das Nicht gut:
rudi.ratlos@host.dom
Besser:
rudi.ratlos@host.dom
Noch besser, mit Text:
rudi.ratlos<AT>host.dom
Mit Grafik:
rudi.ratlos<img src="at.png" alt="AT" ... />host.dom
Bei einer Grafik besteht das Problem, dass diese vom Aussehen statisch ist, das Aussehen des umgebenden Textes u.U. nicht immer gleich ist, z.B. in unterschiedlichen Browsern oder durch Farbänderung beim Überfahren eines Links. HTML: String in Entity-Schreibweise wandelnEine einfache (eventuell nicht besonders wirksame) Methode, um Email-Adressen in HTML-Seiten unkenntlich zu machen, um sie vor Spammern zu verbergen, ist, sie in Entity-Schreibweise zu wandeln. Das folgende Perl-Skript wandelt einen beliebigen String in Entity-Schreibweise:
Beispiel: $ ./str-to-entity 'rudi.ratlos@...'
rudi.ratlos
@...
Montag, 25. Januar 2010SSH: Timeout unterbindenClientseitig$ echo "ServerAliveInterval 120" >> /etc/ssh/ssh_config Wenn der Server 120 Sekunden kein Paket gesendet hat, sendet der Client ein Dummy-Paket zum Server. Serverseitig$ echo "ClientAliveInterval 120" >> /etc/ssh/sshd_config $ /etc/init.d/ssh reload Wenn der Client 120 Sekunden kein Paket gesendet hat, sendet der Server ein Dummy-Paket zum Client. SSH: Automatisch einloggenEin automatisches Login führt SSH durch, wenn auf der Zielmaschine der Öffentliche Schlüssel des eigenen Accounts hinterlegt ist. Der Öffentliche Schlüssel wird auf der Zielmaschine zum Zielaccount hinzugefügt mittels: $ cat id_rsa.pub >>.ssh/authorized_keys2 Die Datei darf nur für den Owner schreibbar sein. Information zur Schlüsselgenerierung: http://www.supportnet.de/faqsthread/806 Freitag, 22. Januar 2010PostgreSQL: TIMESTAMP nach EPOCH wandeln und zurückTIMESTAMP WITHOUT TIME ZONE nach EPOCH
Umwandlung eines
sql> SELECT EXTRACT(EPOCH FROM TIMESTAMP
'1970-01-01 00:00:00' AT TIME ZONE 'UTC') AS t;
t
---
0
Entscheidend ist hier der Zusatz " sql> SELECT EXTRACT(EPOCH FROM TIMESTAMP '1970-01-01 00:00:00') AS t; t ------- -3600 Erläuterungen
EPOCH nach TIMESTAMP WITHOUT TIMEZONE
Umwandlung von Epoch-Sekunden in einen
sql> gkss=# SELECT TIMESTAMP 'epoch' + 0 * INTERVAL '1 second' AS t;
t
---------------------
1970-01-01 00:00:00
Erläuterungen
Donnerstag, 21. Januar 2010Verzeichnisse via rsync abgleichenVerzeichnisbaum spiegeln (local => remote)$ rsync -avz --delete dir1/ user@host:dir2
Der trailing Slash bei
Bei Angabe der Option Via ssh$ rsync -e ssh -avz --delete dir1/ user@host:dir2 Via ssh mit speziellem Port$ rsync --rsh='ssh -p port' -avz --delete dir1/ user@host:dir2 Mittwoch, 20. Januar 2010Perl-Operationen auf SymlinksFür den Umgang mit Symlinks stellt Perl eine Reihe von Builtins zur Verfügung, die nicht unbedingt offensichtlich sind. Hier eine kurze Übersicht:
Dienstag, 19. Januar 2010Liste der zusätzlich installierten Perl-ModuleWie ermittele ich, welche Perl-Module über das Grundsystem hinaus installiert wurden? Die Antwort liefert das Kommando: $ perldoc perllocal Das Ergebnis ist ein formatiertes POD-Dokument, das die Installationshistorie aller per make install oder ./Build install installierten Module aufführt. Das Dokument wird mit der Installation des ersten Moduls angelegt. Unmittelbar nach Installation des Core-Systems ist es noch nicht vorhanden, da noch kein zusätzliches Modul installiert wurde. Mit jeder Modul-Installation wird ein Eintrag am Ende hinzugefügt. Wird ein Modul mehrfach installiert, taucht es mehrfach auf. ProgrammLiefere die Namen der zusätzlich installierten Module, alphabetisch sortiert, ohne Doubletten: 1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 6 my %mod; 7 my $cmd = 'perldoc -u perllocal'; 8 open(my $fh,'-|',$cmd) or die "ERROR: open failed ($!)"; 9 while (<$fh>) { 10 if (/^=head2.*\|(.*)>/) { 11 $mod{$1} = 1; 12 } 13 } 14 close($fh) or die qq|ERROR: Command failed: "$cmd" (Exit Code: $?)\n|; 15 16 for my $mod (sort keys %mod) { 17 print "$mod\n"; 18 } 19 20 # eof Mittwoch, 13. Januar 2010IconsSammlung von mehreren tausend qualitativ hochwertigen Desktop- und Web-Icons: http://www.iconarchive.com/ Fugue Icons: http://p.yusukekamiyamane.com/ Dienstag, 12. Januar 2010GIMP OperationenFarbe transparent machen
Menüpunkt: " Unicode: ISO-8859-1 nach UTF-8 konvertiereniconv - Convert encoding of given files from one encoding to another $ iconv -f ISO-8859-1 -t UTF-8 INPUT >OUTPUT tcs - translate character sets $ tcs -f 8859-1 INPUT >OUTPUT Speicherbedarf von Perl-VariablenDer Speicherbedarf von einzelnen Perl-Variablen und komplexeren Datenstrukturen lässt sich mit Devel::Size ermitteln. Hier die Werte für Perl 5.10 auf einem 32-Bit System. (Eine andere Betrachtung - Messung des verbrauchten virtuellen Speichers bei großen Datenstrukturen - hat Peter J. Holzer angestellt: http://www.hjp.at/programming/perl/memory/) Skalare
Perl alloziert bei Strings jeweils 4 Bytes im Voraus, vermutlich um jedes UTF-8 Zeichen speichern zu können. Obige Berechnung geht von 1-Byte-Zeichen aus. Enthält der String UTF-8 Zeichen mit 2, 3 oder 4 Byte, vergrößert sich der Platzbedarf entsprechend. Arrays
Perl vergrößert ein Array schrittweise auf 4, 8, 16, 32, 64, ... Elemente. D.h. wird das 4. Element zugewiesen, vergößert Perl intern schon auf 8 Elemente usw. Für jedes Element alloziert Perl einen Pointer (4 Bytes). Die angegebene Größe ist der Netto-Speicherbedarf des Array, d.h. der Speicherbedarf der (skalaren) Werte kommt noch hinzu. Hashes
Perl vergrößert einen Hash schrittweise auf 8, 16, 32, 64, ... Elemente. D.h. wird das 8. Element zugewiesen, vergößert Perl intern auf 16 Elemente usw. Für jeden Key alloziert Perl vorab einen Pointer (4 Bytes). Zusätzlich kommt mit zunehmender Anzahl Buckets ein wachsender Overhead von 9, 10, 11, ... Bytes je Key hinzu. Die Größe des Key geht auch mit ein. Bei der Messung unten ist der Key der String "EintragNNNN", also 11 Zeichen lang. Die angegebene Größe ist der Netto-Speicherbedarf des Hash, d.h. der Speicherbedarf der Werte kommt noch hinzu. MessungPerl Version: 5.012001 Skalar ohne Wert: 16 Bytes Referenz: 16 Bytes Integer: 16 Bytes Float: 24 Bytes String - leer: 28 Bytes String - 1 1-Byte Zeichen: 28 Bytes (Diff: 0) String - 2 1-Byte Zeichen: 28 Bytes (Diff: 0) String - 3 1-Byte Zeichen: 28 Bytes (Diff: 0) String - 4 1-Byte Zeichen: 32 Bytes (Diff: 4) String - 5 1-Byte Zeichen: 32 Bytes (Diff: 0) String - 6 1-Byte Zeichen: 32 Bytes (Diff: 0) String - 7 1-Byte Zeichen: 32 Bytes (Diff: 0) String - 8 1-Byte Zeichen: 36 Bytes (Diff: 4) String - 9 1-Byte Zeichen: 36 Bytes (Diff: 0) String - 10 1-Byte Zeichen: 36 Bytes (Diff: 0) String - 11 1-Byte Zeichen: 36 Bytes (Diff: 0) String - 12 1-Byte Zeichen: 40 Bytes (Diff: 4) String - 16 1-Byte Zeichen: 44 Bytes (Diff: 4) String - 20 1-Byte Zeichen: 48 Bytes (Diff: 4) Array - leer: 36 Bytes Array - 4 Elemente: 52 Bytes (Diff: 16) - 13.0 Bytes/Key Array - 8 Elemente: 84 Bytes (Diff: 32) - 10.5 Bytes/Key Array - 16 Elemente: 148 Bytes (Diff: 64) - 9.2 Bytes/Key Array - 32 Elemente: 276 Bytes (Diff: 128) - 8.6 Bytes/Key Array - 64 Elemente: 532 Bytes (Diff: 256) - 8.3 Bytes/Key Hash - leer: 68 Bytes Hash - 4 Keys: 248 Bytes (Diff: 180) - 62.0 Bytes/Key Hash - 8 Keys: 460 Bytes (Diff: 212) - 57.5 Bytes/Key Hash - 16 Keys: 820 Bytes (Diff: 360) - 51.2 Bytes/Key Hash - 32 Keys: 1604 Bytes (Diff: 784) - 50.1 Bytes/Key Hash - 64 Keys: 3172 Bytes (Diff: 1568) - 49.6 Bytes/Key Hash - 128 Keys: 6308 Bytes (Diff: 3136) - 49.3 Bytes/Key Hash - 256 Keys: 13604 Bytes (Diff: 7296) - 53.1 Bytes/Key Hash - 512 Keys: 25124 Bytes (Diff: 11520) - 49.1 Bytes/Key Hash - 1024 Keys: 54308 Bytes (Diff: 29184) - 53.0 Bytes/Key Programm1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 6 use Devel::Size; 7 8 print "Perl Version: $]\n"; 9 10 my $s1; 11 print 'Skalar ohne Wert: ',Devel::Size::size(\$s1)," Bytes\n"; 12 13 my $s2 = \$s1; 14 print 'Referenz: ',Devel::Size::size(\$s2)," Bytes\n"; 15 16 my $s3 = 4711; 17 print 'Integer: ',Devel::Size::size(\$s3)," Bytes\n"; 18 19 my $s4 = 1234.567; 20 print 'Float: ',Devel::Size::size(\$s4)," Bytes\n"; 21 22 my $s5 = ''; 23 my $nLast = Devel::Size::size(\$s5); 24 print "String - leer: $nLast Bytes\n"; 25 26 for my $i (1..12,16,20) { 27 $s5 = 'x'x$i; 28 my $n = Devel::Size::size(\$s5); 29 print "String - $i 1-Byte Zeichen: $n Bytes (Diff: ",$n-$nLast,")\n"; 30 $nLast = $n; 31 } 32 33 my @a1; 34 $nLast = Devel::Size::size(\@a1); 35 print "Array - leer: $nLast Bytes\n"; 36 37 for my $i (4,8,16,32,64) { 38 my @a2 = (1..$i); 39 my $n = Devel::Size::size(\@a2); 40 my $diff = $n-$nLast; 41 my $avg = $n/$i; 42 printf "Array - $i Elemente: $n Bytes (Diff: $diff) - %.1f Bytes/Key\n", 43 $avg; 44 $nLast = $n; 45 } 46 47 my %h1; 48 $nLast = Devel::Size::size(\%h1); 49 print "Hash - leer: $nLast Bytes\n"; 50 51 for my $i (4,8,16,32,64,128,256,512,1024) { 52 my %h2; 53 for (my $j = 1; $j <= $i; $j++) { 54 $h2{sprintf 'Eintrag%04d',$j} = $j; 55 } 56 # @h2{(1..$i)} = (1..$i); 57 my $n = Devel::Size::size(\%h2); 58 my $diff = $n-$nLast; 59 my $avg = $n/$i; 60 printf "Hash - $i Keys: $n Bytes (Diff: $diff) - %.1f Bytes/Key\n",$avg; 61 $nLast = $n; 62 } 63 64 # eof Montag, 11. Januar 2010Text-Eingabefelder per CSS gestalten<input type="text" id="e" name="text" size="20" /> Text: UmrahmungRahmen von 1px Breite statt der normalen Dekoration.
#e {
border: 1px #999 solid;
}
Hintergrundfarbe
Die Hintergrundfarbe des Eingabefeldes ändern, wenn es mit der Maus überfahren wird
(
#e:hover, #e:focus {
background-color: #eee;
}
FontEin Text-Eingabefeld sollte m.E. normalerweise einen monospaced Font eingestellt haben, nur dann entspricht die optische Feldbreite exakt der Anzahl der Zeichen, die in das Feld passen.
#e {
font-family: monospace;
}
Samstag, 9. Januar 2010Cellspacing per CSS unterdrückenIn HTML: <table cellspacing="0"> Per CSS (
#t {
border-collapse: collapse;
}
#t > td {
padding: 0;
}
Dreispaltiges Seitenlayout mit CSSLayout mit Kopf, Fuss und drei Spalten: ![]() Der HTML- und CSS-Code, der dies realisiert: <div id="header"> Header </div> <div id="left"> Left </div> <div id="right"> Right </div> <div id="middle"> Middle </div> <div id="footer"> Footer </div> #header { clear: both; } #left { float: left; width: 80px; } #right { float: right; width: 80px; } #middle { padding: 0 80px 0 80px; } #footer { clear: both; } Anmerkungen
Validierung von HTML- und CSS-CodeDas W3C stellt zwei Services zur Validierung von HTML- und CSS-Code zur Verfügung:
HTML-Validator: http://validator.w3.org/ Um den HTML- bzw. CSS-Code einer Seite direkt zu validieren, können folgende Links in die Seite eingebaut werden. Aus dem Referer-Header ermittelt der Validator die Ausgangsseite und ruft diese ab. Das geht natürlich nur, wenn die Seite öffentlich zugreifbar ist. Validierung von XHTML-Code<a href="http://validator.w3.org/check/referer?ss=1"> <img src="valid-xhtml10.png" width="88" height="31" alt="Valid XHTML 1.0!" /> </a>
Der URL-Parameter Validierung von CSS2-Code
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img src="valid-css2.png" width="88" height="31" alt="Valid CSS!" />
</a>
Freitag, 8. Januar 2010Grundlegende PostgreSQL-AdministrationPostgreSQL ist meiner Meinung nach das beste frei erhältliche Relationale Datenbanksystem. Hier die wichtigsten Kommandos, um damit an den Start gehen zu können. PostgreSQL RDBMS installieren (Debian)# apt-get install postgresql Zum DB-Admin machen# su - postgres Nur von diesem Unix-Account aus kann nach der Installation eine Connection zum DBMS aufgebaut werden. Liste der existierenden Datenbanken$ psql -l [Liste] Nach der Installation existiert zunächst nur die Datenbank postgres. Datenbank erzeugen/zerstören$ createdb DB ... $ dropdb DB</pre> Liste der existierenden Benutzer$ psql postgres=# \du oder postgres=# SELECT rolname FROM pg_roles; Benutzer anlegen/entfernen$ createuser USER Shall the new role be a superuser? (y/n) y ... $ dropuser USER Benutzer sind global für alle Datenbanken einer Installation. Zunächst existiert nur der Benutzer postgres. Soll der User USER von einem anderen Account als dem entsprechenden Unix-Account connecten können, muss ein Passwort vergeben werden. Option -P. DatenbankzugriffIst ein DB-User erzeugt, kann dieser vom gleichnamigen Unix-Account oder per Passwort, falls eins vergeben wurde, von einem anderen Account per psql auf die Datenbank zugreifen. USER$ psql DB Welcome to psql 8.3.6, the PostgreSQL interactive terminal. ... DB=# Liste der existierenden Objekte
Exportieren/Importieren
Session-EinstellungenDatumsformatDatumsangaben im Format YYYY-MM-DD SET datestyle TO iso, ymd select localtimestamp(0); liefert die Zeit im Format: 2009-03-12 17:38:20 ZeichensatzClient arbeitet mit ISO-8859-1: SET client_encoding TO iso88591 Client arbeitet mit UTF-8: SET client_encoding TO utf8 Siehe: http://www.postgresql.org/docs/8.3/static/multibyte.html#AEN27449 Der clientseitige Zeichensatz kann jederzeit umgeschaltet werden. Wenn Daten mit unterschiedlichem Encoding verarbeitet werden, besteht die Möglichkeit, vor dem Schreiben auf die Datenbank das clientseitige Encoding umzuschalten. Die Konvertierung wird dann vom Server übernommen. \-Escapes in Stringliteralen verbietenSET standard_conforming_strings TO on Server-Zugriff von externen HostsDie folgenden Einträge ermöglichen den Zugriff von allen Hosts für alle User und alle Datenbanken.
Server neu starten# /etc/init.d/postgresql-X.Y restart Upgrade auf eine neue VersionSiehe Kapitel "Upgrading" in der Doku. Donnerstag, 7. Januar 2010YouTube Video in HTML-Seite einbettenHier der Code, wie er von YouTube vorgeschlagen wird:
<object width="$WIDTH" height="$HEIGHT">
<param name="movie" value="$URL"></param>
<param name="allowFullScreen" value="$FS"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="$URL"
type="application/x-shockwave-flash"
allowscriptaccess="always"
allowfullscreen="$FS"
width="$WIDTH"
height="$HEIGHT">
</embed>
</object>
Im Falle eines Films im Steitenverhältnis 4:3, wie oben, errechnen sich z.B. folgende Playergrößen: 120 x 115 (klein oben - es wird keine Zeit und kein Slider angezeigt) 160 x 145 (mittel oben - es wird keine Zeit angezeigt) 240 x 205 (groß oben - Fullscreen-Button ist explizit abgeschaltet) 320 x 265 (1. YouTube-Vorschlag) 425 x 344 (2. YouTube-Vorschlag) 480 x 385 (3. YouTube-Vorschlag) 640 x 505 (4. YouTube-Vorschlag)Film automatisch abspielen Der Film wird nach dem Laden automatisch abgespielt, wenn den YouTube-URLs der Parameter &autoload=1 hinzugefügt wird. Film ab einer bestimmten Position wiedergebenDer Film startet ab Position N Sekunden, wenn dem URL der Search-String #t=Ns angefügt wird. Beispiel: #t=65s Der Film beginnt bei 65 Sekunden. Es ist auch die Angabe in Stunden, Minuten und Sekunden, möglich. Die allgemeine Syntax lautet: #t=NhMmKs Qualitätsangaben&fmt=6 verwendet die Qualität 320×240 bis 448×336, Flash 7 video @ 900Kbps; Audio @ 44.1KHz 96Kbps Mono CBR. &fmt=18 verwendet die Qualität 480×360, H.264 Video @ 512Kbps; Audio @ 44.1KHz 128Kbps Stereo. &fmt=22 verwendet 720p HD Video Format. Weitere YouTube URL-Tipshttp://blog.pcspezialist.de/2009/04/21/10-praktische-youtube-url-tricks/ Änderungen an SerendipityFavicon hinzugefügtZu Datei: templates/default/index.tpl Homelink2 auf Artikelübersicht geändertZu index.php?/archives/summary.html in Datei: templates/default/index.tpl Style der Serendipity Admin-Oberfläche ändernDie Admin-Oberfläche bietet keine getrennte Einstellung für den eigenen Style - entweder der Haupt-Style ändert den Style der Admin-Oberfläche mit oder es bleibt bei dem (für meinen Geschmack) nicht sonderlich schönen Default. Die Admin-Styles sind in den Verzeichnissen der Haupt-Styles in $ find templates -type d | grep admin$ ./carl_contest/admin ./competition/admin ./contest/admin ./bulletproof/admin ./default-rtl/admin ./default/admin Ein Style, der keinen Admin-Style definiert, kann mit einem fremden Admin-Style ausgestattet werden, indem ein fremdes admin Verzeichnis (eines anderen Style) dorthin kopiert wird oder ein Symlink auf dieses angelegt wird: $ cd templates/MYSTYLE $ ln -s ../OTHERSTYLE/admin . Perl-Interpreter über Shebang-Zeile suchen#!/usr/bin/env perl Mit dieser Shebang-Zeile wird der Perl-Interpreter über die Environment-Variable
Installation von SerendipityMeine Wahl der Blog-Software ist auf Serendipity gefallen, da ich es neulich positiv erwähnt gefunden habe und meine anschließende Recherche ergeben hat, dass es wohl tatsächlich gut ist. Als ersten technischen Eintrag schreibe ich auf, wie ich Serendipity from scratch auf meinem Debian Web-Host installiert habe. Zwar gibt es Serendipity auch fix und fertig als Debian-Paket, aber das ist in Debian/Stable schon älter. Außerdem ist diese Anwendung für mich wichtig genug, dass ich alles im Detail kontrollieren möchte, einschließlich programmierung, und keinesfalls will, dass die Debian-Paketverwaltung mir mit Updates dazwischen kommt. Homepage von Serendipity: http://www.s9y.org/ Schritt 1: Herunterladen der Software Auf der Homepage bekommt man die aktuelle Version als Tarball und auch eine Beschreibung für die manuelle Installation. Diese hat den Titel Fresh Installation. Sie ist gut, aber in einigen Punkten nicht ausführlich genug. Ich beschreibe hier die Dinge, die ich bei meiner Installation dort nicht gefunden habe. Schritt 2: Auspacken des Pakets Das Paket, in meinen Fall Schritt 3: Benötigte Debian-Pakete installieren # deb-install php5 # apt-get install postgresql # apt-get install php5-pgsql # apt-get install imagemagick Serendipity ist in PHP5 programmiert. Als DBMS verwende ich PostgreSQL. Imagemagick wird von Serendipity zur Bildbearbeitung gebraucht. Schritt 4: Apache Konfiguration Im Serendipity-Paket scheint keine Apache-Config dabei zu sein. Ich habe diese
von der Debian-Version übernommen, mit der ich zuvor herumgespielt habe. Lediglich
die Pfade brauchte ich anpassen. Der URL des Blog wird
Alias /blog /opt/serendipity/1.5.1
<Directory /opt/serendipity/1.5.1>
Options -Indexes +FollowSymlinks
DirectoryIndex index.php
<IfModule mod_php5.c>
php_flag session.use_trans_sid off
php_flag register_globals off
</IfModule>
AllowOverride All
order allow,deny
allow from all
<Files *.tpl.php>
deny from all
</Files>
<Files *.tpl>
deny from all
</Files>
<Files *.sql>
deny from all
</Files>
<Files *.inc.php>
deny from all
</Files>
<Files *.db>
deny from all
</Files>
</Directory>
Die Datei wird als # apache2ctl restart Schritt 5: PostgreSQL-Datenbank einrichten Für die Datenbank-Einrichtung sind drei Dinge zu tun:
Datenbank und User erzeugen: # su - postgres $ createdb serendipity $ createuser -P serendipity Password: Wichtig ist bei Schritt 6: Konfiguration und Administration von Serendipity Anschließend auf Bei Anmeldeaufforderung per "John Doe" mit Passwort "john" anmelden. Benutzername und Passwort sollten nach der Anmeldung als erstes geändert werden. Danach kann Serendipity im Detail den persönlichen Wünschen angepasst werden. Samstag, 2. Januar 2010Haftungsausschluss1. Inhalt des BlogDer Autor übernimmt keinerlei Gewähr für die Aktualität, Korrektheit, Vollständigkeit oder Qualität der bereitgestellten Informationen. Haftungsansprüche gegen den Autor, welche sich auf Schäden materieller oder ideeller Art beziehen, die durch die Nutzung oder Nichtnutzung der dargebotenen Informationen bzw. durch die Nutzung fehlerhafter und unvollständiger Informationen verursacht wurden, sind grundsätzlich ausgeschlossen, sofern seitens des Autors kein nachweislich vorsätzliches oder grob fahrlässiges Verschulden vorliegt. Das Angebot ist freibleibend und unverbindlich. Der Autor behält es sich ausdrücklich vor, Teile der Seiten oder das gesamte Angebot ohne gesonderte Ankündigung zu verändern, zu ergänzen, zu löschen oder die Veröffentlichung zeitweise oder endgültig einzustellen. 2. Verweise und LinksBei direkten oder indirekten Verweisen auf fremde Webseiten (Hyperlinks), die außerhalb des Verantwortungsbereiches des Autors liegen, würde eine Haftungsverpflichtung ausschließlich in dem Fall in Kraft treten, in dem der Autor von den Inhalten Kenntnis hat und es ihm technisch möglich und zumutbar wäre, die Nutzung im Falle rechtswidriger Inhalte zu verhindern. Der Autor erklärt hiermit ausdrücklich, dass zum Zeitpunkt der Linksetzung keine illegalen Inhalte auf den zu verlinkenden Seiten erkennbar waren. Auf die aktuelle und zukünftige Gestaltung, die Inhalte oder die Urheberschaft der verlinkten/verknüpften Seiten hat der Autor keinerlei Einfluss. Deshalb distanziert er sich hiermit ausdrücklich von allen Inhalten aller verlinkten/verknüpften Seiten, die nach der Linksetzung verändert wurden. Diese Feststellung gilt für alle innerhalb des eigenen Internetangebotes gesetzten Links und Verweise sowie für Fremdeinträge in vom Autor eingerichteten Gästebüchern, Diskussionsforen, Linkverzeichnissen, Mailinglisten und in allen anderen Formen von Datenbanken, auf deren Inhalt externe Schreibzugriffe möglich sind. Für illegale, fehlerhafte oder unvollständige Inhalte und insbesondere für Schäden, die aus der Nutzung oder Nichtnutzung solcherart dargebotener Informationen entstehen, haftet allein der Anbieter der Seite, auf welche verwiesen wurde, nicht derjenige, der über Links auf die jeweilige Veröffentlichung lediglich verweist. 3. Urheber- und KennzeichenrechtDer Autor ist bestrebt, in allen Publikationen die Urheberrechte der verwendeten Grafiken, Tondokumente, Videosequenzen und Texte zu beachten, von ihm selbst erstellte Grafiken, Tondokumente, Videosequenzen und Texte zu nutzen oder auf lizenzfreie Grafiken, Tondokumente, Videosequenzen und Texte zurückzugreifen. Alle innerhalb des Internetangebotes genannten und ggf. durch Dritte geschützten Marken- und Warenzeichen unterliegen uneingeschränkt den Bestimmungen des jeweils gültigen Kennzeichenrechts und den Besitzrechten der jeweiligen eingetragenen Eigentümer. Allein aufgrund der bloßen Nennung ist nicht der Schluss zu ziehen, dass Markenzeichen nicht durch Rechte Dritter geschützt sind! Das Copyright für veröffentlichte, vom Autor selbst erstellte Objekte bleibt allein beim Autor der Seiten. Eine Vervielfältigung oder Verwendung solcher Grafiken, Tondokumente, Videosequenzen und Texte in anderen elektronischen oder gedruckten Publikationen ist ohne ausdrückliche Zustimmung des Autors nicht gestattet. 4. DatenschutzSofern innerhalb des Internetangebotes die Möglichkeit zur Eingabe persönlicher oder geschäftlicher Daten (Emailadressen, Namen, Anschriften) besteht, so erfolgt die Preisgabe dieser Daten seitens des Nutzers auf ausdrücklich freiwilliger Basis. Die Inanspruchnahme und Bezahlung aller angebotenen Dienste ist - soweit technisch möglich und zumutbar - auch ohne Angabe solcher Daten bzw. unter Angabe anonymisierter Daten oder eines Pseudonyms gestattet. Die Nutzung der im Rahmen des Impressums oder vergleichbarer Angaben veröffentlichten Kontaktdaten wie Postanschriften, Telefon- und Faxnummern sowie Emailadressen durch Dritte zur Übersendung von nicht ausdrücklich angeforderten Informationen ist nicht gestattet. Rechtliche Schritte gegen die Versender von sogenannten Spam-Mails bei Verstössen gegen dieses Verbot sind ausdrücklich vorbehalten. 5. Rechtswirksamkeit dieses HaftungsausschlussesDieser Haftungsausschluss ist als Teil des Internetangebotes zu betrachten, von dem aus auf diese Seite verwiesen wurde. Sofern Teile oder einzelne Formulierungen dieses Textes der geltenden Rechtslage nicht, nicht mehr oder nicht vollständig entsprechen sollten, bleiben die übrigen Teile des Dokumentes in ihrem Inhalt und ihrer Gültigkeit davon unberührt. Freitag, 1. Januar 2010Eröffnung des Developer LogbuchsIch habe beschlossen, ein Technik-Blog zu führen, in dem ich meine Erfahrungen aufschreibe. Primär als Nachschlagewerk zur eigenen Erinnerung, aber auch als mögliche Hilfe für andere. Ich selbst schlage oft im Web nach, wenn ich auf eine Fragestellung oder ein Problem stoße und meistens ist etwas darunter, was mir weiter hilft. Dies soll mein bescheidener Beitrag zur Wissensweitergabe im Zeitalter des Internet sein.
(Seite 1 von 1, insgesamt 75 Einträge)
|
VideoKalenderSucheStatistikLetzter Artikel:
15.05.2012 09:41 75 Artikel insgesamt
Links
|