[ about | pics | projects | repos | weblog ]

[ ~derf :: Interblag ]

Archives: 2008 2009 2010 2011 2012 2013

The perl module LWP::UserAgent (at version 6.08) does not play well with custom CA certificates and most online resources seem to be outdated. Two notes on that (which may or may not apply to non-Debian systems as well):

  • If a certificate failed verification, you will not get a nice error message. Temporary workaround: sudo mv /usr/share/perl/5.20.1/IO/Socket/IP.pm{,_} (and then later sudo mv /usr/share/perl/5.20.1/IO/Socket/IP.pm{,_})
  • LWP::UserAgent does not support custom certificates installed with update-ca-certificates. You'll need HTTPS_CA_FILE=/etc/ssl/certs/ca-certificates.crt in your environment.
2013-12-18 20:10

Koffeinhaltige Schokolade

Schokolade ist gut, Koffein auch. Go figure.

Hier gibt's erstmal nur ein Rezept, Bilder oder sonstige Details folgen irgendwann™ in schön auf chaosdorf.de.

Zutaten

  • 100 bis 300 Gramm schmelzbare Schokolade (Mit der Zartbitterkuvertüre zu 79ct/200g von Rewe hab ich gute Erfahrungen gemacht)
  • bis zu 10 Gramm Pulver(gemisch) je 100 Gramm Schokolade.
  • Gerätschaften: Mikrowelle, Porzellanschale, breiter Teller/Plastikdose, Messer

Das Pulver kann recht beliebig sein, bisher getestet wurden feingemahlener Kaffee und Guarana (siehe Ergebnisse). Mischungen davon oder reines Koffein sollten entsprechend dosiert ebenfalls kein Problem sein.

Zubereitung

  • Porzellanschale mit der Schokolade füllen
  • 2 bis 3 Minuten auf mittlerer Stufe (600 .. 700W) in die Mikrowelle stellen
  • Rausnehmen und die halbflüssige Schokolade mit einem Messer o.ä. zerkleinern
  • Wieder 1 bis 2 Minuten in die Mikrowelle, das ganze solange wiederholen, bis in der Schale eine homogene flüssige Schokoladenmasse ist (kleine Bröckchen können i.d.R. durch Rühren beseitigt werden, einzelne Blasen auf der Oberfläche sind kein Prolem). Erfahrungsgemäß sind drei Mikrowelleniterationen ausreichend
  • Pulver gründlich unterrühren
  • Schokolade in geeignetes mit Alufolie ausgekleidetes Gefäß ausgießen und durch Schwenken / Streichen gleichmäßig verteilen — Empfehlenswert sind Plastikdosen oder nicht zu flache Teller
  • 3 bis 6 Stunden (je nach Raumtemperatur) warten
  • Masse mit Alufolie umdrehen, Alufolie ablösen, Schokoblock in geeignete Stücke schneiden
  • Nom

Die Schokolade am besten nicht unter Luftabschluss (bsp. geschlossene Plastikdose) erkalten lassen; andernfalls nimmt sie beim Erkalten Luft auf, wird unangenehm bröselig und schmeckt nach wenig.

Ergebnisse

Mit Kaffeepulver (11g/100g): Man schmeckt den Kaffee sehr stark raus und merkt auch zügig das Koffein, dafür hält es nicht all zu lange an. Üblicherweise bleibt etwas Pulver an den Zähnen halften. Koffeingehalt 3 bis 5 mg je Gramm.

Mit Guaranapulver (8g/100g): Schmeckt (fast?) wie normale Schokolade, es bleibt auch nichts an den Zähnen haften. Wirkt mit ca. 2 Stunden Versatz, dann aber durchaus merkbar. Koffeingehalt 3 bis 7 mg je Gramm.

Mit Kaffee und Guarana (unbekannte Dosis): Schmeckt weiterhin nur nach Kaffee, hat aber Sofort- und Spätwirkung. Durchaus empfehlenswert.

Kommentare

An @derfnull oder derf@chaosdorf.de. Oder direkt im Chaosdorf / auf dem 30C3.

2013-03-05 10:25

Backups and Monitoring

(tldr: Beware of pipes with set -e. And write more checks.)

At the Chaosdorf, we have an automated weekly backup of all servers and other hosts. The script uses set -e right at the start and reports its success with send_nsca just before quitting. A freshness threshold is used to produce an alert if a backup run does not report in time.

This sounds like nothing can go wrong without being noticed. However, there is a problem: backup_external uses pipes. And in a pipe, only the return value of the last command is actually evaluated:

descent ~ > ( set -e; false | true; echo foo )
foo

So, if something along the way (e.g. tar or gpg) has a problem, the script will happily run along and report its success at the end. Which will result in something like this:

flux ~ > sudo ls -l /chaosdorf/backups/09 | fgrep feedback
-rw-r--r-- 1 chaosdorf chaosdorf    0 Mar  4 00:03 feedback.chaosdorf.dn42_etc.tar.xz.gpg
-rw-r--r-- 1 chaosdorf chaosdorf  24K Mar  4 00:03 feedback.chaosdorf.dn42_packages
-rw-r--r-- 1 chaosdorf chaosdorf    0 Mar  4 00:03 feedback.chaosdorf.dn42_root.tar.xz.gpg
-rw-r--r-- 1 chaosdorf chaosdorf    0 Mar  4 00:03 feedback.chaosdorf.dn42_usr_local.tar.xz.gpg
-rw-r--r-- 1 chaosdorf chaosdorf    0 Mar  4 00:03 feedback.chaosdorf.dn42_var_local.tar.xz.gpg
-rw-r--r-- 1 chaosdorf chaosdorf    0 Mar  4 00:03 feedback.chaosdorf.dn42_var_log.tar.xz.gpg

In this case, it was likely GPG refusing to work on a readonly filesystem (it's an embedded host running on an SD card, so making it readonly makes sense).

The good thing about this is: The failed backups are all empty files, and finding empty files is as easy as running find -size 0. So now we have a second check on the receiving host to alert me whenever an obviously failed backup is transferred.

So:

  • Never, ever trust a single check
  • If you have the disk space, keep more than just the most recent three backups (I actually did this right)
2012-08-19 16:05

Semantic Mediawiki Examples

It's been two months since we installed Semantic Mediawiki and Semantic Forms in the Chaosdorf Wiki, and I've got to say it's pretty nice.

The basic idea of semantic mediawiki is: Pages are not just there, but can have Properties (like a language, hostname, preview image etc.), and based on these properties one can create queries, such as selecting all pages in Category:Projects which have a description and a preview image.

This article is not meant as an Introduction to Semantic Mediawiki (see the link for that), just some real-world examples of what's possible. I tried to sort the examples by ascending complexity.

Eliminating Category: pages

wiki/Foo certainly looks nicer than wiki/Category:Foo. It's already possible to set a #REDIRECT from the former to the latter, but that still leaves the long page title as default. Using the query

{{#ask: [[Category:Foo]]
 | format = ul
}}

you get a listing very similar to a category page. If the page containing the query is in the category itself, it will even be marked bold.

Example: https://wiki.chaosdorf.de/History

Listing pages with a certain property (e.g. items in a certain room)

Assume you have a page for every room or location of your whatever (Hackerspace in our case), and also a page for every item inside. If you have a property describing the item's location (which is very easy with Semantic Forms, it even provides autocompletion of existing locations), there's a simple way to have every location page list its contents.

Each item page specifies its location as [[Has location::Someplace]], the query is

{{#ask: [[Has location::{{PAGENAME}}]]
 | format = ul
 | intro=Beinhaltet:
}}

The intro text is only displayed if there is something to list, so if the location has no items, nothing will be displayed.

Example: https://wiki.chaosdorf.de/Serverraum (the query is hidden inside https://wiki.chaosdorf.de/Template:Location)

Pretty-listing pages with certain properties (e.g. preview images)

With projects or resources in a wiki, it'd be very nice to have more than a simple list of page names, like a table with preview images and short descriptions. It is of course possible to create one manually, but mainting it quickly becomes a pain or is simply forgotten. Also, duplicate information sucks.

So: Create a Mediawiki Template and a Form for project/resource pages, which contain (with properties) its name, description, preview image (if available), etc. Semantic Mediawiki allows formatting its query results with templates, so it's not hard to get a reasonably nice list of projects with images.

Also, Semantic Forms allows uploading the preview image from inside the Form, so when creating a project/resource page one does not even need to open Special:Upload in another tab and copy-paste filenames.

The query in this case is

{{#ask: [[Category:Projects]] [[Has image::+]] [[Duplicate::false]]
| format = template
| template = PreviewSMW
| outrotemplate = PreviewEnd
| link = none
| ?Has description
| ?Has image
}}

So it formats each result with Template:PreviewSMW, does not link to the pages by itself (the template will do it), and also passes the properties Has description and Has image of each page to the template. Example: https://wiki.chaosdorf.de/Projects

Library system with lend book / return book buttons

This is not what Semantic Mediawiki is meant for, but a fun experiment. Create a page for each book you have (in our case in the custom Book namespace). The most important part here is the lent by property, which corresponds to the lent argument of Template:Book and Form:Book and, if set, is the user who has currently lent it.

A list of all books can be obtained in the standard query fashion:

{{#ask: [[Book:+]]
 | format = table
 | ?Has author = Autor
 | ?Has ISBN = ISBN
 | ?lent by = ausgeliehen?
}}

Thanks to the #autoedit function, it's possible to add lend / return buttons to each book page (via Template:Book, which we already have anyways to fill in the properties and have a book form). First, let's have some markup:

{{#if:{{{lent|}}}|
{{#autoedit:form=book
 | target=Book:{{PAGENAME}}
 | link type=button
 | link text=zurückgeben
 | Book[lent]=
 | Book[lent at]=now
 | namespace=Book
 | reload
}}
|
{{#autoedit:form=book
 | target=Book:{{PAGENAME}}
 | link type=button
 | link text=ausleihen
 | Book[lent]={{#USERNAME:}}
 | Book[lent at]=now
 | namespace=Book
 | reload
}}
}}

The {{#if: condition | yes | no }} part comes from Parserfunctions, which is not part of Semantic Mediawiki / Semantic Forms, but also nice to have. The two buttons are mutually exclusive, so it makes sure only the correct one is shown.

target=Book:{{PAGENAME}} tells autoedit to edit the current page, and reload makes sure a wiki user sees the effect of their actions. (otherwise the page would be changed, but the user would still see the its old version).

The interesting parts are Book[lent] and Book[lent at]. Right in the first line, we tell autoedit to use the "Book" form, and in these two places we access parameters of that form. The first one works like using {{Book | ... | lent = someuser}}.

In Book[lent at]=now, the "now" becomes the YYYY/MM/DD representation of today. This works because in Form:Book, the lent at parameter declared to be a date. (If lent at corresponded to a property of type date, this would not even be neccessary).

First, there's an excellent parallel port howto on epanorama.net.

What I'd like to add: You can't just control LEDs or relay coils / transistors with the parallel port, it's also pretty easy to talk to microcontrollers (an ATTiny 2313 in my case).

interfacing

Basically, you need one or two parallel port pins as inputs to the AVR, and then come up with some sort of protocol.

one-wire

No clock signal, so we rely on proper timing. The most primitive solution is to toggle the pin n times and have the AVR increment a counter on every toggle, then read the counter value after a fixed time without counter increment has passed. Excruciatingly slow, but dead simple to implement both on the computer and the AVR.

two-wire

One pin for data, one for the clock (e.g. set data, then toggle clock, set an AVR interrupt on rising edge on clock to read data pin). I didn't try it yet.

more?

So far, the computer talks to the AVR but not vice versa. Two-way communication shouldn't be hard, but I didn't try it yet. If I do, I may write a new entry.

hardware

To be on the safe side, I decided to completely isolate the parallel port from the rest of the circuit.

components used:

  • KB817 opto-coupler. forward voltage ~1.2V, collector-emitter voltage 35V/6V
  • 3.3K resistor between opto-coupler and parallel port, since the parallel port provides 2.4 to 5V
  • BC338-40 transistor to make sure the opto-coupler output is registered by the microcontroller

The rest is usual stuff. The parallel port circuit is located in the bottom left of the schematic.

software

microcontroller

Assuming the transistor (optocoupler) is connected to INT0

  • set an interrupt on INT0 rising edge: increment counter and reset timeout
  • set a timer interrupt: check timeout, if zero handle counter as command

code snippet:

ISR(INT0_vect)
{
    cli();
    command++;
    cmd_wait = 6;
}

ISR(TIMER1_COMPA_vect)
{
    if (cmd_wait)
        cmd_wait--;
    else if (command) {
        run_command();
        command = 0;
    }
}

the whole file is available on github: main.c

computer

I'm using the parapin library, see pgctl.c on github. Note that timing is important here, so I'm running the code at the lowest possible niceness.

That's it. An example project is available as derf/pgctl on github.

The whole point of this post is: interfacing with the parallel port is easy. It doesn't have a future, but if you still have one, you can use it for quite a lot of things.

(because it's way more awesome than using just a Wiimote)

For this to work, you will need an up-to-date cwiid installation, the most important part is commit b54bd05.

Next, check out neverball svn and apply tilt wii.patch.

Build it (make ENABLE_TILT=wii), then run ./neverball and press the Balance Board's red sync button.

If everything works out, the Power LED should turn on. Now you can use the mouse / keyboard to select the level to play, and then control the level itself using the Balance Board.

There's a (really low-quality) Video (also on Youtube) available. I hope to have a higher resolution and less laggy one by saturday.

For the record, the complete patched tilt wii.c is also available.

Update:
I've got a new Video! (also on Youtube). As you can see, controlling neverball this way is pretty hard :)

With the most recent Patch, you can control the level with the balance board and the camera and menus with the wiimote. Usage: Start neverball, connect wiimote, wait 'til the leds stop blinking, then connect balance board. There are some timing issues right now, so if it crashes while connecting the devices, just try again.

Als Person, die nichts mit Mikrocontrollern am Hut hat, fragt man sich ja immer, was für eine Wissenschaft das eigentlich ist. Man hört von gefährlichen Fusebits, kaputtgeflashten Chips, hat vielleicht auch schonmal jemanden mit ISP/JTAG-Gedöns rumfummeln sehen und stellt insgesamt fest, dass das alles unheimlich kompliziert aussieht.

Das schöne an der Sache ist: Wenn man sich erstmal mit beschäftigt, merkt man schnell, dass es viel simpler ist, als man denkt. Genaugenommen sind die ersten Schritte dank Internet, insbesondere mikrocontroller.net sehr einfach.

Programmer und Chips

Zunächst mal vorweg: Alles folgende bezieht sich auf die Atmel AVR-Prozessoren.

An AVR-Programmier- und -Testboards gibt's mehr als genug, z.B. das Arduino-Projekt. Da kann man sich irgendwas aussuchen, von dem bekannt ist, mit welchen Methoden welche Arten von Chips programmiert werden können. Aus der Menge der programmierbaren Chips besorgt man sich ebenfalls ein paar Stück und schon kann man loslegen.

Es ist übrigens auch möglich, AVR-Chips direkt am LPT-Port zu programmieren, für den Anfang ist ein fertiges Board aber deutlich empfehlenswerter. Da hat man nämlich ein paar LEDs und Taster am µc dranhängen, so dass man direkt rumspielen kann, ohne erst eine Schaltung zu löten.

Atmelboard von Pollin

In meinem Fall wurde es das Atmel-Evaluationsboard. Das ganze gibt's als Bausatz oder auch Fertigmodul, und mikrocontroller.net und der Entropia haben auch Artikel darüber.

Das Atmelboard von Pollin unterstützt mehrere verschiedene AVR-Typen, ich hab mir ein paar ATtiny2313-Chips geholt, mit 1.95 Euro pro Chip kann man bei denen nicht viel falschmachen. So ein ATtiny ist zwar sehr eingeschränkt (2kB ROM, 128 Byte RAM, 128 Byte EEPROM), aber für erste Testprogramme reicht er locker, und später wird man ohnehin feststellen, dass auf so einen µc viel mehr draufpasst, als man denkt.

Software

Wenn man nun sein Board hat, braucht man die nötige Software, i.d.R. reicht es dazu aus, avrdude und avr-libc (sollten gcc-avr und binutils-avr mitziehen) zu installieren. Ziel ist jedenfalls, dass man einen funktionierenden Compiler für den AVR-Plattform (gcc-avr) und ein Proramm zum Flashen des Chips (avrdude) hat.

Vorbereitung

Für alles weitere empfiehlt sich auch sehr, einfach mal durch AVR-Tutorial und AVR-GCC-Tutorial durchzuklicken, da steht alles (und noch viel mehr), was man wissen muss.

Man kann schonmal einen Chip in den Programmer stecken und ihn an Strom und PC anschließen. Je nach Interface (USB / Seriell) wird er meist als /dev/ttyUSB0 oder /dev/ttyS0 angesprochen. Beim Pollinboard ist unbedingt zu beachten, dass das serialle Kabel an den ISP-Anschluss und nicht RS232 kommt. Letzterer macht nichts kaputt, tut aber auch nichts für uns.

Nun fehlt nur noch eine Methode, um Code zu kompilieren und auf den AVR zu spielen, und etwas Code zum Testen.

Ich selbst bevorzuge C-Code, welcher mittels eines Makefiles kompiliert und dann (ebenfalls vom Makefile) auf den µc programmiert werden kann. Siehe dazu Beispiel Makefile. Ich verwende die korrigierte Fassung aus dem Artikel (direktlink).

Man muss in dem Makefile nur noch drei Dinge einstellen: Den verwendeten Chip (MCU), den Programmer (AVRDUDE_PROGRAMMER) und den Port (AVRDUDE_PORT). Für meine Konstellation wäre das:

MCU = attiny2313
AVRDUDE_PROGRAMMER = ponyser
AVRDUDE_PORT = /dev/ttyS0

Dinge tun!

Damit wäre die Vorbereitung fertig. Für einen ATtiny auf dem Pollinboard gäbe es noch dieses simple Testprogramm (main.c):

#include <avr/io.h>

int main (void) {

    DDRD = (1 << PD5);
    PORTD = (1 << PD5);

    while (1);

    return 0;
}

Dieses Programm mit make kompilieren und anschließend mit make program auf den AVR übertragen lassen. Man sieht nun jede Menge Ausgaben von avrdude, ganz unten sollte jetzt stehen, dass alles geklappt hat.

Das Programm tut nichts anderes, als den I/O-Pin PD5 auf Output zu setzen, einzuschalten und dann zu loopen. Auf dem Board ist an PD5 eine LED angeschlossen, diese sollte nun leuchten.

Das war's dann auch schon. Falls der Controller funktioniert ist alles schön, falls nicht einfach mal auf mikrocontroller.net und in den Kommentaren des Makefiles rumwühlen, wahrscheinlich stimmt irgendeine Einstellung nicht. Ich selbst kam in das Glück, nicht debuggen zu müssen.

Und so weiter

Für alles Weitere (und sehr gute Erklärungen dazu, was die einzelnen Codezeilen des Beispiels genau tun) sei noch einmal auf das AVR-GCC-Tutorial ( sowie sämtliche andere Artikel auf der Seite :p ) verwiesen. Das Tutorial behandelt im Gegensatz zu meinem Blogpost auch so ziemlich alle Methoden, mit denen man was tun kann.

Man sieht jedenfalls, dass "Mikrofoo" eigentlich ziemlich simpel ist, man sollte sich nur nicht von der Länge der Howtos oder den Fachbegriffen erschlagen lassen.

Ein Wort zu Fuses noch: Solange man einfach nur rumspielt, kann man die meist komplett ignorieren. Somit hat man auch keine Möglichkeiten, seinen Controller kaputtzuflashen, schlimmstenfalls hängt man ihn durch einen Programmierfehler auf, was mit 'nem einfachen Reset / Flashen einer korrigierten Programmversion behoben wird.

Ich teste gerade für die geplante Lichtdecke im Chaosdorf ein paar LED-Halogenersatzbirnen... und ich muss schon sagen, soo schlecht sind die Teile gar nicht.

Zum Test da sind zwei kaltweiße 1W-Birne (96lm, entspricht ca. 10W Halogen), zwei kaltweiße in 2.4W (160lm, ca. 20W Halogen) und zwei warmweiße in 2.4W (140lm, ebenfalls ca. 20W Halogen).

LED-Packungen

Im Vergleich zu den 300 bis 600 Lumen einer 30W-Halogenbirne sind sie natürlich noch dunkel, aber die kaltweiße 2.4W-Birne sieht schon so aus, als könnte man sie tatsächlich als Arbeitslicht benutzen.

Hier mal ein paar Bilder der Lampen, aufgrund verschiedener Kameraeinstellungen taugen sie nicht wirklich als Vergleich, aber geben zumindest 'ne grobe Idee.

Ganz kalt bleiben die Leuchten im Betrieb nicht, aber die Temperaturentwicklung hält sich sehr in Grenzen. Zumindest konnte ich sie nach 'ner halben Stunde Betrieb noch schmerzfrei anfassen.

Auf der Rückseite ist übrigens deutlich mehr Elektronik, als man erwarten würde:

Lampenrückseite

Mal schauen, was draus wird. Tolle Spielzeuge sind so LED-Lampen schonmal.

2011-04-24 17:29

Gedanken zur Spackeria

Die datenschutzkritische Spackeria ist ja schon länger ein Thema... da komm ich nicht umhin, auch mal meinen Braindump dazu ins Netz zu pusten ;-)

Einen der Hauptgedanken versteh ich ja als "Wenn man schon Daten ins Netz stellt, dann sollte man sich auch nicht wundern, wenn sie benutzt werden", bzw. sobald Daten irgendwie die eigene Kontrolle verlassen (z.B. auch an Bekannte weitergegeben werden), ist es letztendlich immer möglich, dass sie öffentlich im Netz landen.

Eigentlich ist das Problem mit den freilaufenden Daten ja gar nicht so neu.

Wenn man mal einen Vergleich aufbaut, hat man das auch bei ganz normaler Kommunikation: Person A erzählt Person B von Dingen. Wenn das einfach nur belangloses/unwichtiges Zeug ist, ist es auch egal, ob es weitererzählt wird. Wenn es sich bei den Dingen aber um irgendetwas privates handelt, sollte Person A schon sehr gut wissen, wem sie es erzählt und wem nicht. Und muss im Zweifelsfall auch damit rechnen, dass die Informationen trotzdem (ggf. noch verändert) weitergetragen werden und z.B. Gerüchte entstehen. Und dass man solche Gerüchte nicht "löschen" kann, sollte klar sein.

Heutzutage: Person A lädt z.B. Bilder für Person B hoch. Auch hier muss sie sich (wenn es potentiell kompromittierendes Material ist) darauf verlassen, dass diese Bilder bei Person B bleiben. Auch hier kann es passieren, dass diese Bilder plötzlich an weitere Personen verbreitet werden und letztendlich "im Internet" landen. Wo man sie, wie hoffentlich jeder weiß, auch nicht mehr rauskriegt (irgendwer hat immer 'ne Kopie gespeichert). Und auch hier können die Bilder verändert ("gephotoshoppt") werden, womit wir dann bei Gerüchten wären.

Von daher: Sobald ich die alleinige Kontrolle über irgendetwas, sei es nun Gedankengut (reale Unterhaltung) oder Daten (Bilder, Videos, whatever) mit Anderen teile, besteht immer die Gefahr, dass diese Anderen mein Vertrauen verletzen und die Daten weiter tragen, als ich will. Es steht jedem selbst frei, zu entscheiden, bei welchen Daten und Personen(gruppen) er dieses Risiko eingeht, und bei welchen er es lieber sein lässt.

Leute dürfen gerne Youtubevideos oder peinliche Partybilder hochladen und als privat / nur einer gewissen Personengruppe zugänglich markieren. Es muss nur zum Allgemeinwissen werden, dass es in solchen Fällen verdammt leicht passieren kann, dass die Bilder dann plötzlich sonstwo landen und dort auch nie und nimmer mehr wegzukriegen sind. Wenn allen Leuten dieses Risiko bewusst ist, werden wir vielleicht auch direkt weniger Datenschutzdrama haben :-)

Was natürlich hilft, ist, Daten direkt für alle öffentlich zu machen. Das ist dann ein anderer Post-Privacy-Gedanke, dass irgendwann einfach sämtliche Daten öffentlich sind, und wenn jeder Mensch peinliche Sachen im Netz stehen hat, ist es für den einzelnen auch egal, da gesellschaftliche Norm. Aber bis sich unsere Gesellschaft dahin entwickelt (wenn sie es denn tut), wird es vermutlich noch ziemlich lange dauern. Von daher empfehle ich dringend, damit jetzt noch nicht anzufangen ;-)

Ein Problem hätte mein Vergleich übrigens: Dateneinbruch.

Gedanken kann niemand aus meinem Kopf stehlen, Daten von meinem PC allerdings sehr wohl. In dem Fall kann man allerdings auch nur zwei Dinge tun — Hoffen, dass die meisten Menschen den Anstand haben, nicht in fremde Systeme einzubrechen und Daten kopieren ("stehlen" ja i.d.r. nicht), und selber seine Systeme sichern. Aber das ist dann wieder ein anderes Problem.

Um bei diesem ganzen Geschwurbel mal zu 'nem Punkt zu kommen: Post-Privacy und die Spackeria sind überhaupt nichts Neues, das Problem, dass Gedanken/Daten in fremde Hände kommen können, wenn man die Kontrolle darüber abgibt, ist uralt. Es wird endlich Zeit, dass die Menschheit sich damit abfindet, anstatt rumzuweinen.

Ich selbst tendier ja auch in Richtung post-privacy, zumindest findet man auf about auch meine Tweets, Software und meinen Musikgeschmack. Und via PGP und die Web2.0-Seiten auch sehr schnell mein soziales Umfeld. Über last.fm kann man sogar grob darauf schließen, wann ich aufstehe und wann ins Bett gehe. So what?

2011-04-24 10:08

feh v1.13 released

Just a quick note: feh v1.13 has been released yesterday. Download.

Its main feature is Xinerama-aware background setting. That is, if you have two or more monitors, feh --bg-fill and the likes will no longer behave as if you just had one display connected, but instead set the image properly scaled on each monitor. This is a bgs feature I've been wanting to implement for quite a while.

If you have a wallpaper which is designed for your multimonitor setup, you can use the --no-xinerama switch to get the old behaviour, e.g. feh --no-xinerama --bg-fill foo.jpg.

The only background option which does not support Xinerama is --bg-tile. The reason for this is that if you use tiling, you probably have a wallpaper which repeats itself and does not care where on the monitor it starts/stops, so there should be no need to care about the monitor setup.

What's also new in this release: When you call feh without file arguments, it will now simply display all images in the current directory instead of exiting. To save you typing those two extra characters after the feh options :-)

As for bugfixes: Reloading finally works properly and not only after the second try (stupid Imlib2 caching...), and you can now use %h and the likes in --title without feh segfaulting when encountering an unloadable image.

That's about it. Now on to feh 1.14. :p

2011-04-07 20:04

Introducing check_websites

As part of the Chaosdorf Admin Team, I recently wrote (and today overhauled) check_websites. You give it a URL and it checks if it is reachable under certain constraints.

All of this can also be achieved with check_http. However, since the Icinga configuration format is extremely verbose, I prefere to configure just one service which then uses check_websites to do all of this in one run.

Right now, it does actually not support that much. To quote its help:

-a, --auth=STRING
  Verify that URL requires auth (HTTP 401)
-o, --ok=STRING
  Verify that URL exists (HTTP 200)
-r, --redirect="FROM TO"
  Verify that FROM is a redirect (HTTP 301) to TO

In our case, we're calling it the following way:
/usr/local/lib/nagios/plugins/check_websites --extra-opts=@/etc/nagios/chaosdorf_websites.ini

On a side note: Nagios::Plugin is really, really awesome.

2011-04-06 09:20

Website stuff

Okay. I decided to have as much website redundancy as one can get with one VM (steel) and one homeserver (aneurysm). I don't really know I got this idea, but it's probably my general backup and redundancy obsession ;-)

Now, the setup is as follows:

  • aneurysm.derf0.net stores data only on aneurysm (/tmp and the like)
  • steel.derf0.net stores data only on steel (/tmp for other files)
  • derf.homelinux.org is the main website, hosted on aneurysm. It is built by ikiwiki and automatically mirrored to steel, where it is reachable as finalrewind.org. Now I just have to decide if I stick to derf.homelinux.org or use finalrewind.org as "main url" for my website...
  • feh.finalrewind.org is also managed by ikiwiki. It is built on aneurysm, automatically mirrored to steel, and served from steel
  • man.finalrewind.org is generated by custom stuff and hosted from aneurysm. Not mirrored yet, will be fixed.
  • lib.finalrewind.org hosts large images and is therefore served from steel. Its "base" is also on steel, aneurysm regularly mirrors from there

This time, I'm using rsync instead of unison to do the syncing, mostly because all the websites have the generation scripts only on one host, so it does not make sense to do a two-way sync. The vhosts are managed by lighttpd with mod_evhost.

On a side note: I had another DynDNS problem yesterday (the FritzBox did not update properly) and finally decided that a homeserver is a nice toy, but when one reaches the point where one has websites which are meant to be available all the time, it's really better to host elsewhere. I think I reached that point a year ago, so... yeah. About time.

The next logical step would be to sync the ikiwiki sources instead of the output and have the git repos etc. on both hosts, so when one goes down I can just push to the other (and maybe change the DNS records). But that's probably a bit overdone, especially for low-traffic sites like mine.

2011-03-27 14:27

Wechsel zu ikiwiki

So. Ich hab jetzt die gesamte Website (abzüglich http://feh.finalrewind.org) von komischen Perl/Shell/Makefile-Gefrickel auf ikiwiki umgestellt. Damit ich endlich mal direkt Inhalt produzieren kann, ohne mich mit irgendwelchem Formatgedöns rumschlagen zu müssen.

Es gibt noch ein paar 404s (z.B. die Changelogs der Projektseiten), aber das Wichtigste sollte eigentlich funktionieren.

Nebenbei kann ich jetzt auch z.B. 'ne richtige Sidebar einbauen, wenn ich denn will.

This started as a proof-of-concept, but it turned out to be actually useful.

The idea: Hey, why not have some widgets. They're shiny (at least when properly designed, mine definitely ain't ;-) ), they show useful information, and you have a little more than just a boring wallpaper on your desktop.

However, I'm using a tiling window manager with pseudo-transparent urxvt terminals. I do see my wallpaper, but never my actual desktop. A widget would be totally useless there.

So, I decided to put the widgets directly onto my wallpaper. Each widget is a script producing a PNG image in /tmp, and those are then overlayed onto the wallpaper using ImageMagick. This has some obvious disadvantages (low update frequency, widgets are non-interactive), but besides that, I really like it. I'll not turn this into a project as I'm not sure how many other people find this useful, but for myself I'll definitely keep it.

Resources: widget list, update script (does some other things as well).

I recently started working on hashl (no project page yet), inspired by (hashcp)[https://github.com/craig/hashcp]. It creates a list of all files below a directory and also stores a hash of their beginning (by default the first 4 MiB, but that's configurable. For music, I usually use 512KiB).

This way, when you find an FTP server or whatever, you don't have to mirror everything and later check if you already have it, but you can tell hashl to scan all files on the FTP server, download only the first few kilo-/megabytes and use those to check if you possibly already have the file on your disk. This of course doesn't prevent having one file in several versions, but against pure duplicates (which are also common) it works well.

So, you don't have to worry about duplicates, and as a side effect, leeching is faster because you do not even transfer any duplicate files.

Or, my usecase: I have an external hard disk for all my videos, and a directory on my netbook containing just a few of them. New videos also end up on the netbook. The hard disk is mounted on /media/argon, the netbook dir is ~/lib/video. hashl stores its database in .hashl.db, /media/argon/.hashl.db is a symlink to ~/lib/video/.argon. ~/lib/video/.hashl.db also points there.

Now, I can use these neat commands:

# whenever I mount the external hard disk, I update the list
descent /media/argon > hashl update
# same, but more verbose
descent /media/argon > hashl -d ~/lib/video/.argon update

# Now, to find out which files in my netbook directory are new (not yet copied)
descent ~/lib/video > hashl find-new
# same
descent ~/lib/video > hashl -d .argon find-new

# As an advantage, I can also use this on remote servers. Let's say I have an
# FTP mounted on /tmp/ftp/foo and the external disk is not connected. I can
# still only leech the videos I do not yet have.
descent /tmp/ftp/foo > hashl -d ~/lib/video/.argon copy ~/lib/video

# And of course, to sync netbook <-> hard disk
descent ~/lib/video > hashl copy /media/argon/filme/incoming
descent ~/lib/video > cd /media/argon
descent /media/argon > hashl update

For me, this tool is a great help, and I'll maybe add some more fun features too (merging databases? Marking a file from a non-connected external storage for retrieval? Moar automation for things I cannot think of yet?). So, stay tuned for the first release, whenever it will happen :p

This is a little perl script to make sure a remote nagios account only runs the checks it is configured to, and in case it somehow gets owned does (hopefully) not do any damage.

Script: forcecommand, Example config: forcecommand.cfg. I recommend the following line for .ssh/authorized_keys: command="/usr/local/lib/nagios/forcecommand",no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding $key

In my icinga, I configured it the following way: In /etc/nagios-plugins/config/ssh.cfg, I added:

define command {
    command_name check_by_ssh_fc
    command_line /usr/lib/nagios/plugins/check_by_ssh -H '$HOSTADDRESS$' -t 50 '$ARG1$'
}

And then use "check_command check_by_ssh_fc!check_apt_updates" etc.

For feh versions <= 1.7 down to at least 1.3.4, feh -G/--wget-timestamp contains an arbitrary code execution hole when called with malicious URLs containing shell characters.

The problem is that --wget-timestamp does a system() call to /bin/cp, handing it the unescaped URL. If the URL were to contain a sequence like ';something', "something" would be interpreted and executed as new shell command.

Constraints: The user must use --wget-timestamp, the URL's command part may (apparently) not contain "obfuscation" like %20 for space etc., and the remote file must exist on the server.

Example: Try feh --wget-timestamp 'https://derf.homelinux.org/stuff/foo;touch lol_hax'. Result.

All in all this is rather improbable, but I'd advise you anyways to update to feh 1.8 ;-)

Ugly hack to automatically connect external monitors using xrandr and udev:

Write SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/libexec/some-x-script.sh" into a udev rules file. This script will (at least on my system ;-) ) now get called every time you either plug in an external VGA connector or remove it.

In this script, you can now use xrandr to set up the monitor. To find out whether it is called after connecting or disconnecting, check /sys/class/drm/card0-VGA-1/enabled (or similar). Example. Happy hacking.

By the way, note that disconnecting the monitor before deconfiguring it with xrandr may break stuff. At least my system doesn not like it and does not accept other monitors until a reboot afterwards - manually calling xrandr --off first will work, of course. YMMV.

It first seems that all functions which are more advanced than "copy music files into .../MUSIC" are not possible without the proprietary Windows Software. But luckily, playlists, images and videos can also easily be converted into a format which the player understands. This post is meant to explain how to use all of the player's features (or at least those I found/used so far ;) ) with linux or any other UNIXish OS.

Music: Like you'd expect: connect player, mount the device, put your songs into .../MUSIC, umount and listen to them. Only possible catch: You may need to sed the device's USB Mode to "MSC". I didn't try MTP, but I believe that one might lead to problems.

Playlists: A little bit more sophisticated. The player supports the m3u format, but only DOS-style. The best way seems to be putting .m3u playlists with relative paths into MUSIC (assuming your songs are also stored in there), then changing all slashes to backslashes (sed 's:/:\:g') and converting the files' linebreaks to DOS format (unix2dos). UNIX line endings will not make the file unreadable, but the last line (the last song) will be missed.

Images: Standard JPEG, but possibly with size limitations (I didn't really test those). What definitely works: convert -resize 220x176.

Movies: This was the hardest part - The player expects a very specific type of MPEG not even mencoder can produce. However (these are the occasions where I really love the Open Source community) there is, of course, a program for it: fuzemux. With this, converting a video becomes a process of three "simple" program calls:

mencoder -msglevel all=0:statusline=5 -ffourcc DX50 -ofps 20 -vf \
pp=li,expand=:::::224/176,scale=224:176,harddup -ovc lavc -lavcopts \
vcodec=mpeg4:vbitrate=683:vmax_b_frames=0:keyint=15:turbo:vpass=1 \
-srate 44100 -af resample=44100:0:1,format=s16le -oac mp3lame \
-lameopts cbr:br=128 ${INPUT} -o ${TMPOUT}

mencoder -msglevel all=0:statusline=5 -ffourcc DX50 -ofps 20 -vf \
pp=li,expand=:::::224/176,scale=224:176,harddup -ovc lavc -lavcopts \
vcodec=mpeg4:vbitrate=683:vmax_b_frames=0:keyint=15:vpass=2 -srate 44100 \
-af resample=44100:0:1,format=s16le -oac mp3lame -lameopts cbr:br=128 \
${INPUT} -o ${TMPOUT}

fuzemux ${TMPOUT} ${OUTPUT}

If this is too much commandline usage for you, there is also video4fuze (Yeah, I already linked to that a few lines above) which does all of this in a quite nice GUI. That site also was a great help for me, I got the mencoder parameters from the source code ;-)

Always quote them with "$var" unless you are either absolutely sure they contain no spaces or you actually want to expand spaces. In the former case, you may want to use "$var" nevertheless for consistency.

Also: ${var} is more readable than $var, especially in cases like "$destdir$prefix/$file". "${destdir}${prefix}/${file}" is a little bit easier to digest. I'm not really sure if I want to use the ${var} form for all variables, though. With "${var}", it might get a little redundant. OTOH, in cases where you don't need quotation (like zsh scripts), ${var} looks better.

Unrelated, but maybe also interesting: I'm currently editing without syntax highlighting. As I can no longer rely on it to help me find stuff, it forces me to write a little more readable code. So I guess I'll keep it disabled.