This is a tale of two approaches to regular expression matching. One of them is in widespread use in the standard interpreters for many languages, including Perl. The other is used only in a few places, notably most implementations of awk and grep. The two approaches have wildly different performance characteristics: .... (Hier geht's zum eigentlichen Artikel)

grep3p.png
grep4p.png

Der Inhalt des Artikels ist relativ interessant. Zwecks Dokumentation blogge ich ihn hiermit.

Es muss halt nicht immer Perl sein. Es geht auch mal mit AWK.

GNU Screen (GNU Screen (GNU Screen))

| No Comments | No TrackBacks

Als Systemadministrator arbeite ich an vielen Sachen parallel. Ich hatte ständig zu viele Fenster (Terminal Emulatoren) auf, was dazu führte, dass viel Zeit dabei drauf ging ein bestimmtes Fenster wiederzufinden. Deswegen habe ich mir nun eine andere Strategie überlegt, mit der ich meine Fensterflut bewerkstelligen kann. Es handelt sich um ein 3-fach verschachteltes GNU Screen.

Auf meiner Workstation habe eine Hauptsession all mit ^ee als Escapesequenz konfiguriert. In dieser Session lege ich beliebig viele Fenster an (im Screenshot lediglich die folgenden Zwei: server und home [in Wirklichkeit sind dort ca. 10 Fenster]). Wobei ich in jedem Fenster eine weitere GNU Screen Session starte mit jeweils ^ww als Escapesequenz. (Im Screenshot z.B. im Fenster "server" habe ich ein Screen mit screen -S server gestartet).

In server kann ich somit weitere Fenster anlegen (Im Screenshot die titan.buetow.org und io.buetow.org). In jedem Serverfenster kann ich mich dann beispielsweise per SSH auf den jeweiligen Server einloggen und eine weitere Screensession starten (mit Standardescapesequenz ^Aa). Auf dem Server titan habe ich laut Screenshot z.B. die beiden Fenster bash und mutt auf.

Durch die verschiedenen Escapesequenzen der verschachtelten Screens kann ich individuell und schnell die Fenster jeder beliebigen Verschachtelungsebene wechseln. Das ist alles am Anfang etwas verwirrend, aber mit etwas Übung erleichtert es die Arbeit erheblich. Idealerweise hat man 2 Monitore am Arbeitsplatz. Ein Monitor für einen maximierten Terminalemulator für Screen, und der andere Monitor für andere Anwendungen (z.B. Browser).

Für Hot-Fixes, Incidents oder Kram, wo man nicht extra ein Screen Fenster für erstellen will kann man mittels Tabbing des Terminalemulators (mrxvt bei mir) temporäre Shells öffnen. Dies sind dann aber nur temporäre Shells, die ich dann wieder für immer schliesse.

gnu-screen-1.png

gnu-screen-2.png

Dies hab ich bereits mehrere Monate in Erprobung und funktioniert einwandfrei :) Ich werde aber noch die Escapesequenz ^ww des zweiten Screens ändern. Da sich diese Sequenz ansonsten mit einem Vim-Kürzel in die Quere kommt.

C++ Reference

| No Comments | No TrackBacks

Ein Klassiker der Referenzen der Programmiersprache C++ ist die Website www.cppreference.com. Die Site ist immer Empfehlenswert (gerade da sie relativ übersichtlich gestaltet ist und man sich relativ schnell zurecht findet). Fragen betreffend C++ im IRC kann ich meist (seit mehreren Jahren) mit einem Verweis darauf beantworten. :)

Domain Key Identified Mail

| No Comments | No TrackBacks

Seit kurzem unterstützt mein Mailserver Domain Key Identified Mail (DKIM).

DomainKeys ist ein Identifikationsprotokoll zur Sicherstellung der Authentizität von E-Mail-Absendern, das von Yahoo entwickelt wurde und seit Ende 2004 in Erprobung ist. Es wurde konzipiert, um bei der Eindämmung von unerwünschter E-Mail wie Spam oder Phishing zu helfen.

Den dazugehörige TXT record im DNS bekommt man wie folgt:

dig -t txt 2010._domainkey.buetow.org

Derzeit ist DKIM nur für die Domäne buetow.org aktiviert.

Online Kernel Patches

| No Comments | No TrackBacks

Lesenswert: ksplice. Hiermit kann man einen Linux Kernel im laufenden Betrieb patchen.

Mittlerweile scheint das Ding für den Produktivbetrieb schon nutzbar zu sein. Größere Kernelupgrades sind mit ksplice allerdings nicht machbar.

Distributed Replicated Block Device

| No Comments | No TrackBacks

Lesenswert: DRBD

drbd.gif

Wer kennt es nicht? Man hat sich in einer SVN Commit Message vertippt und kann es nicht rückgängig machen. Eine Commit Message ist lediglich ein Log-Property. Diese kann man wie folgt nachträglich ändern:

svn propset svn:log 'New commit message' -r1022 --revprop

Dies geht allerdings nur, wenn Serverseitig der pre-revprop-change hook konfiguriert wurde.

header_checks @ postfix mta

| No Comments | No TrackBacks

Für jedes Formular im Internet verwende ich eine eigene Catchall-Email-Adresse. So kann ich nachvollziehen welcher Anbieter welche Newsletter zu verantworten hat. Mittlerweile haben sich einige E-Mail Adressen derart verbreitet, dass ich darüber täglich Newsletter von irgendwelchen mir nicht bekannten Anbietern bekomme. Das Abmelden des jeweiligen Newsletters bringt wenig, da ein paar Tage später ein anderer Newsletter eines anderen Anbieters über diese Adresse verschickt wird.

Deswegen kann ich nun jede Adresse mittels PCRE dediziert blocken wie folgt:

io:/etc/postfix# cat header_checks 
/^to: *(citibank|r|microsoft|macbookpro)@mx\.buetow\.org/ 
    REJECT WTF! Don't send spam!
/^to: *(wizzair|christopher)@paul\.buetow\.org/ 
    REJECT WTF! Don't send spam!
/^subject:.*VIAGRA/ 
    REJECT Instead of Viagra I need Beer for free!
io:/etc/postfix# grep header_check main.cf
header_checks = regexp:/etc/postfix/header_checks


pwgrep v0.5 is out

| No Comments | No TrackBacks

Nach v0.4 folgt nun v0.5 von pwgrep.

Die einzige Änderung ist der 'Offline Mode'. Der Offline-Mode sollte verwendet werden, wenn keine Verbindung mit dem Internet besteht (weil dann zum Beispiel kein Subversion oder CVS zur Verfügung steht).

Bsp.: pwgrep -o foobar

Ansonsten hat sich nichts Weiteres getan ;)

N95 8GB als WLAN Access Point

| No Comments | No TrackBacks

Heute ist für ein paar Stunden mein DSL ausgefallen. Allerdings konnte ich dann noch mittels UMTS über mein N95 8GB online gehen. Mit der Applikation "JoikuSpot" konnte ich das N95 in einen WLAN-Hotspot verwandeln. Damit hab ich dann eine Stoerungsmeldung mittels Ticketsystem erstellt. Nach einer weiteren Stunde kam ich dann wieder über mein normales DSL online.

joikuspot12.jpg

JoikuSpot ist neben ProfiMail eine weitere kostenpflichtige Applikation für mein Handy. Es lohnt sich aber! Um z.B. eben schnell mit dem Netbook schnell online zu gehen, wenn man seinen UMTS-Stick gerade nicht dabei hat. Das Handy hat man sowieso meist dabei.

Zwar hätte ich das Ganze auch per Bluetooth oder N95 als USB-Modem bewerkstelligen können, allerdings ist der Hotspot komfortabler und einfacher und ich kann jedes beliebige Gerät (auch mehrere auf einmal) damit online bringen.

E-Mails auf meinem Nokia N95 8GB

| No Comments | No TrackBacks

Mein Nokia N95 (mittlerweile die 8GB Version) ist nicht mehr das Neuste was der Markt der Smartphones bietet. Allerdings bin ich damit noch rundum zufrieden. Ein kleines Manko war jedoch der mitgelieferte E-Mail client. Daher hab ich mir die App ProfiMail von Lonely Cat Games gekauft. Die App ist jeden Cent wert! Sie verwandelt mein Nokia zu einem vollwertigen E-Mail Client (IMAP, mehrere Postfaecher, SSL, Bildbetrachter, eingebauter Browser fuer HTML Mails, u.v.m). ProfiMail ist zwar nicht Open Source (i.A. preferiere ich Open Source Software) aber ProfiMail ist eine gerechtfertigte Ausnahme. Es gibt auch eine 30 Tage kostenlose Testversion. Dabei verstreicht nur 1 Testtag, wenn man an diesem Tag auch wirklich ProfiMail gestartet hat. Hier ein paar Screenshots (aus dem Internet geklaut):

qqqqqtr6.jpg

Das Gute an Nagios ist, dass sich Checks relativ einfach und straight forward selbst scripten lassen. So wie der Folgende, der ein FTP Backup Account auf freien Speicherplatz ueberprueft:

#!/usr/local/bin/bash 
# check_ftp_df.sh 
# Free FTP disk space nagios check 
# (c) Paul Buetow 2010

set -e

WARN=$1
CRITICAL=$2
FTPSPACE=$3
USERNAME=$4
PASSWORD=$5
BACKUPSERVER=$6

if [ -z $BACKUPSERVER ]; then
        echo "UNKNOWN: Could not execute the check"
        exit 3
fi

du=`echo du -s . | lftp -u $USERNAME,$PASSWORD $BACKUPSERVER | \
   sed 's/\.//'`

eval df=$(( $FTPSPACE - $du ))

if [ $? -ne 0 ]; then
        echo "UNKNOWN: Wrong credentials?"
        exit 3
fi

if [ $df -lt $CRITICAL ]; then
        echo "CRITICAL: Free disk space: $df KBytes"
        exit 2

elif [ $df -lt $WARN ]; then
        echo "WARNING: Free disk space: $df KBytes"
        exit 1
fi

echo "OK: Free disk space: $df KBytes"
exit 0

todotxt

| No Comments | No TrackBacks

Auf http://todotxt.com findet ihr ein kleines nettes Shell-Skript welches eine Todo-Liste managed und zwar nach dem Motto Weniger ist mehr.

todotxt20-header.png

Genau das Richtige für seine kleine private Todo-Liste auf der Arbeit. Dort gibt es genügend interne Ticketsysteme. Aber keines nur für sich alleine. So muss man die Kollegen nicht mehr mit Tickets an sich selbst zuspamen.

Neuer GPG Key

| No Comments | No TrackBacks

Heute ist mein alter GPG/PGP Schlüssel abgelaufen.

Alt:

0xF4B6FFF0 2008-06-12 [expired: 2010-06-12]

Neu:

0x37EC5C1D 2010-06-12

Der Neue ist unbegrenzt gültig. Zudem hat er mehr Bit. Er wurde bereits auf einen Keyserver geladen.

Lazy Evaluation in Standard ML

| No Comments | No TrackBacks
Standard ML benutzt, im gegensatz zu Haskell, "Strict Evaluation" und keine "Lazy Evaluation" als Auswertungsstrategie. Mithilfe von Lazy Evaluation lassen sich auf besonders elegnater Art und Weise unendliche Datenstrukturen behandeln (z.B. unendliche abzählbare Folgen (wie eine Liste von allen Paaren aller natürlicher Zahlen nat_paare oder eine Liste von allen Paaren aller natürlichen Zahlen außer 0 nat_paare_nicht_null).) In Sprachen mit Strict Evaluation läßt sich jedoch meist Lazy Evaluation emulieren wie z.B. im Folgenden anhand von ML demonstriert:

type 'a lazy = unit -> 'a;
fun force (f:'a lazy) = f ();
fun delay x = (fn () => x) : 'a lazy;

datatype 'a sequ = NIL | CONS of 'a * 'a sequ lazy;

fun first 0 s = []
  | first n NIL = []
  | first n (CONS (i,r)) = i :: first (n-1) (force r);

fun filters p NIL = NIL
  | filters p (CONS (x,r)) =
    if p x 
      then CONS (x, fn () => filters p (force r)) 
      else filters p (force r);

fun nat_paare () = 
  let
    fun from_pair (x,0) = 
      CONS ((x,0), fn () => from_pair (0,x+1))
    | from_pair (up,dn) = 
      CONS ((up,dn), fn () => from_pair (up+1,dn-1))
   in from_pair (0,0)
  end;

(* Test 
val test = first 10 (nat_paare ())
*)

fun nat_paare_nicht_null () =
  filters (fn (x,y) => x > 0 andalso y > 0) (nat_paare ());
  
(* Test
val test = first 10 (nat_paare_nicht_null ());
*)
Da Haskell bereits Lazy Evaluation eingebaut hat, geht es hier einfacher. Hier muss auch kein neuer Datentyp definiert werden, da Haskell-Listen bereits lazy sind.:

{- Just to make it look like the ML example -}
first = take
filters = filter

{- Implementation -}
nat_paare = from_pair 0 0
   where
      from_pair x 0 = [x,0] : from_pair 0 (x+1)
      from_pair up dn = [up,dn] : from_pair (up+1) (dn-1)

{- Test: 
first 10 nat_paare
-}

nat_paare_nicht_null = 
   filters (\[x,y] -> x > 0 && y > 0) nat_paare

{- Test: 
first 10 nat_paare_nicht_null
-}

811-1.jpgIch hab seit Kurzem das Buch Time Management for System Administrators (es gibt hierfür auch eine Version in Deutsch) durch.

Als hauptberuflicher Linux Systemadministrator entspreche ich exakt der Zielgruppe dieses Buches. Das Buch ist verständlich geschrieben und läßt sich flüssig lesen. Außerdem schläft man beim Lesen dieses Buches nicht ein, da es auch viel Humor (aus dem Lifestyle eines Sysadmins) mitbringt (Hier wird beispielsweise die CPU eines Computers und der L1 und L2 Cache zum Vergleich mit dem menschlichen Gehirn herangezogen. Sich auf etwas zu konzentrieren bedeutet nämlich etwas im CPU Cache zu haben. CPU-Power sollte man sich im Gehirn zudem sinnvoll einteilen. So sollte man in der Tageszeit, wo man sich am besten konzentrieren kann, die schwierigen Aufgaben lösen und nicht triviale Tickets bearbeiten und zu langweiligen Meetings gehen und die CPU idlen lassen :-).

Die dort beschriebenen Methoden lassen sich fast alle in meinen Alltag einbringen. Mich hat das Buch ein gutes Stück weitergebracht. Hier die offizielle Zusammenfassung des Buches:

"Time is a precious commodity, especially if you're a system administrator. No other job pulls people in so many directions at once. Users interrupt you constantly with requests, preventing you from getting anything done. Your managers want you to get long-term projects done but flood you with requests for quick-fixes that prevent you from ever getting to those long-term projects. But the pressure is on you to produce and it only increases with time. What do you do? The answer is time management. And not just any time management theory--you want Time Management for System Administrators, to be exact. With keen insights into the challenges you face as a sys admin, bestselling author Thomas Limoncelli has put together a collection of tips and techniques that will help you cultivate the time management skills you need to flourish as a system administrator. Time Management for System Administrators understands that an Sys Admin often has competing goals: the concurrent responsibilities of working on large projects and taking care of a user's needs. That's why it focuses on strategies that help you work through daily tasks, yet still allow you to handle critical situations that inevitably arise. Among other skills, you'll learn how to: * Manage interruptions * Eliminate timewasters * Keep an effective calendar * Develop routines for things that occur regularly * Use your brain only for what you're currently working on * Prioritize based on customer expectations * Document and automate processes for faster execution What's more, the book doesn't confine itself to just the work environment, either. It also offers tips on how to apply these time management tools to your social life. It's the first step to a more productive, happier you."

Standard ML und Haskell #2

| No Comments | No TrackBacks
Lindig2.jpegNochmal ein kleiner Vergleich zwischen Standard ML und Haskell. Dieses Mal geht es um Funktionen höherer Ordnung. Die Syntax ist fast die Selbe. Jedoch Haskell ist ein kleines bischen weniger verbose. Hier sind 4 Funktionen, jeweils in einer Standard ML Version (oben) und in einer Haskell Version (unten):

fun make_map_fn f1 = fn (x,y) => f1 x :: y
make_map_fn f1 = \x y -> f1 x : y

fun make_filter_fn f1 = 
     fn (x,y) => if f1 x then x :: y else y
make_filter_fn f1 = 
     \x y -> if f1 then x : y else y

fun my_map f l = foldr (make_map_fn f) [] l
my_map f l = foldr (make_map_fn f) [] l

fun my_filter f l = foldr (make_filter_fn f) [] l
my_filter f l = foldr (make_filter_fn f) [] l
Die Haskell Syntax ist darauf optimiert so wenig Boilerplate Code wie möglich zu produzieren. Standard ML ist da allerdings auch nicht gerade schlecht (die Funktionen my_map und my_filter haben in Haskell und in SML quasi die selbe Syntax. SML benutzt lediglich noch das Schlüsselwort fun).

Die interaktive SML shell lässt zu Wünschen übrig. So versuch ich vergebens einen Befehl die aktuell geladene Datei erneut einzulesen. In Haskell (ghci) geht das z.B. mit dem Befehl :r (r für reload) wie folgt:

*Main> :r
[1 of 1] Compiling Main             ( temp.hs, interpreted )
Ok, modules loaded: Main.

Bei SML hingegen muss ich mit Strg+D den interaktiven Prompt verlassen und die Bash-Histoy benutzen um "sml meinesourcecodedatei.sml" erneut einzulesen. Zwar gibt es einen sml-Befehl eine Sourcecodedatei einzulesen, aber der ist zu lang um ihn jedes Mal erneut eingeben zu können (Mein sml hat auch keine History-Funktion).

Standard ML und Haskell

| No Comments | No TrackBacks
Derzeit erarbeite ich mir die Grundlagen der funktionalen Programmiersprache Standard ML (Studium - Fortgeschrittene Konzepte funktionaler Programmierung). Da ich schon ein bischen Haskell kann, konnte ich es mir nicht nehmen die Aufgaben auch in einer Haskell-Version zu implementieren. Wie man sieht sind sich SML und Haskell (zumindest bisher in den Grundlagen) sehr ähnlich. Allerdings ist die Syntax von Haskell an einigen Stellen etwas "fortgeschrittener". Es werden in Haskell insgesamt etwas weniger Schlüsselwörter (z.B. val, end, fun, fn...) und Kommas in der Syntax verwendet. Ausserdem gibt es in Haskell die (optionale) Möglichkeit die Typen einer Funktion explizit hinzuschreiben. Was leserlicher ist und zudem Programmierfehler vermeidet. Was ich bisher bei SML vermisse sind auch die sog. Pattern Guards die es in Haskell gibt. I.A. gefällt mir bisher Haskell besser als SML, u.A. auch da Haskell sich "pur funktional" schimpft während SML auch von imperativen Konzepte explizit Gebrauch macht. Aber soweit bin ich in SML noch nicht. Hier ein paar Funktionen in SML und in Haskell im Vergleich:

Standard ML:

datatype ''a multi 
  = EMPTY
  | ELEM of ''a
  | UNION of ''a multi * ''a multi

Haskell:

data (Eq a) => Multi a
  = Empty
  | Elem a
  | Union (Multi a) (Multi a) 
  deriving Show

Standard ML:

fun number (EMPTY) _ = 0
  | number (ELEM x) w = if x = w then 1 else 0
  | number (UNION (x,y)) w = (number x w) + (number y w)

fun test_number w = 
  number (UNION (
    EMPTY, 
    UNION (
      ELEM 4,
      UNION (
        ELEM 6,
        UNION (
          UNION (
            ELEM 4,
            ELEM 4
          ),
        EMPTY)
      )
    )
  )) w

Haskell:

number Empty _ = 0
number (Elem x) w = if x == w then 1 else 0

test_number w = 
  number (Union 
    Empty
    (Union 
      (Elem 4)
      (Union
        (Elem 6)
        (Union
          (Union
            (Elem 4)
            (Elem 4)
          )
        Empty)
      )
    )
  ) w

Standard ML:

fun simplify (UNION (x,y)) = 
    let fun is_empty (EMPTY) = true
        | is_empty _ = false
       val x' = simplify x
       val y' = simplify y
     in if (is_empty x') andalso (is_empty y')
        then EMPTY
       else if (is_empty x')
        then y'
       else if (is_empty y')
        then x'
       else UNION (x', y')
    end
  | simplify x = x

Haskell:

simplify (Union x y) 
    | (isEmpty x') && (isEmpty y') = Empty
    | isEmpty x' = y'
    | isEmpty y' = x'
    | otherwise = Union x' y'
  where 
    isEmpty Empty = True
    isEmpty _ = False
    x' = simplify x
    y' = simplify y
simplify x = x

Standard ML:

fun delete_all m w =
  let fun delete_all' (ELEM x) = if x = w then EMPTY else ELEM x
      | delete_all' (UNION (x,y)) = UNION (delete_all' x, delete_all' y)
      | delete_all' x = x
   in simplify (delete_all' m)
  end

Haskell:

delete_all m w = simplify (delete_all' m)
  where
    delete_all' (Elem x) = if x == w then Empty else Elem x
    delete_all' (Union x y) = Union (delete_all' x) (delete_all' y)
    delete_all' x = x


Standard ML:

fun delete_one m w =
  let fun delete_one' (UNION (x,y)) = 
      let val (x', deleted) = delete_one' x 
       in if deleted 
        then (UNION (x', y), deleted)
        else let val (y', deleted) = delete_one' y 
           in (UNION (x, y'), deleted)
          end
        end
      | delete_one' (ELEM x) = 
        if x = w then (EMPTY, true) else (ELEM x, false)
      | delete_one' x = (x, false)
      val (m', _) = delete_one' m 
    in simplify m'
  end

Haskell:

delete_one m w = do
    let (m', _) = delete_one' m 
      simplify m'
  where
    delete_one' (Union x y) = 
      let (x', deleted) = delete_one' x 
       in if deleted 
        then (Union x' y, deleted)
        else let (y', deleted) = delete_one' y 
             in (Union x y', deleted)
    delete_one' (Elem x) = 
        if x == w then (Empty, True) else (Elem x, False)
    delete_one' x = (x, False)

dec060dc3.54370_1.pngIch hab nun eine Gruppe auf Xing gegründet. Und zwar "Deklarative Programmierung".

Die deklarative Programmierung ist ein Programmierparadigma, bei dem die Beschreibung des Problems im Vordergrund steht. Der Lösungsweg wird dann "automatisch" ermittelt. Zu den deklarativen Programmiersprachen gehören:
funktionale Sprachen (z. B. LISP, ML, Miranda, Gofer, Haskell, Erlang)
logische Sprachen (z. B. Prolog) und einige mehr. Deklarative Programmierung unterscheidet sich somit von dem verbreiteteren Programmierparadigma der imperativen Programmierung.

Freue mich immer auf neue Mitglieder! (Auch personen die sich noch nicht mit der deklarativen Programmierung auskennen sind herzlich eingeladen).

Monadic Perl

| No Comments | No TrackBacks
Nach C++ hab ich auch etwas gefunden, wo Monaden in Perl implementiert wurden. Es funktioniert, aber in Haskell wirkt die Implementierung von Monaden noch etwas eleganter. Aber das Resultat kommt dem in Haskell recht nahe:

sub ev
{
    my $term = $_[0];
    if($term =~ /^$con/)
    {
        return Return($1);
    }
    elsif($term=~/^$div/)
    {
        my $numer=$1; my $denom=$3;
        return DO {
                    my $n <- ev($numer);
                    my $d <- ev($denom);
                    my $g <- tick();
                    Return( $n / $d );
                  }
    }else{die "Syntax Error: $term";}
}

Recent Comments

  • avinash: excellent image used for migration. request you for using it read more
  • pb: After watching the first 4 lectures: It is worth it read more
  • pb: Even shorter: sc.butow.org Even shorter shorter: sc.pbtw.org read more
  • pb: I marked this obsolete. I am not using .bue anymore. read more
  • pb: Well it seems like a lot has changed. I am read more
  • Byte: Hehe, nice! read more
  • Neme: Danke. Ist gespeichert. read more
  • Byte: Hehe, seems like a fine book for computer geeks. I read more
  • Byte: Hehe, seems like a fine book for computer geeks. I read more
  • Coke: Nice cam, nice buy! I like Canon 2. read more

Recent Assets

  • grep3p.png
  • grep4p.png
  • gnu-screen-2.png
  • gnu-screen-1.png
  • drbd.gif
  • joikuspot12.jpg
  • qqqqqtr6.jpg
  • todotxt20-header.png
  • 811-1.jpg
  • dec060dc3.54370_1.png

Find recent content on the main index or look in the archives to find all content.