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)
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).
Attaching custom hardware to the parallel port
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.
Playing Neverball with the Wii Balance Board

(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.
Einstieg in Mikrocontroller-Programmierung
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.
LED-Lampen als Ersatz für Halogenbirnen
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).
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:
Mal schauen, was draus wird. Tolle Spielzeuge sind so LED-Lampen schonmal.
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?
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
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.
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.
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.
Ghetto Widgets: Putting PNGs onto your wallpaper
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).
hashl: Hash your files, copy only new stuff
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
Running remote nagios checks with an SSH forcecommand
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.
Code execution hole in feh --wget-timestamp
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 ;-)
Automatically connecting external monitors (udev+xrandr)
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.
SanDisk "Sansa Fuze" with Linux
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 ;-)
A few notes on shell variables
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.
Fuckup
Situation: SSH von meinem Netbook auf meinen Server lagt, sobald größere Dateien übertragen werden, enorm. Mit netcat schafft man 10 MB/s, via SSH bestenfalls 10 KB/s.
Das besonders tolle daran: Das Problem tritt nur in eine Richtung auf (server→netbook schafft die volle Bandbreite) und nur über LAN. Per WLAN gehen zwar grundsätzlich nur maximal 2MB/s durch die LeitungwLuft, aber dafür stabil auch per SSH.
Ich glaube, ich will gar nicht wissen, woran das liegt. Aber vielleicht finde ich es ja irgendwann mal raus :>
My coding principle
First, create something that works. It doesn't need to be nice or perfect, it should just work (and if possible not introduce big security risks).
Based on that, write tests.
As time passes, slowly fix bugs and beautify the code.
I've (first unconsciously ;) used this for several years now and I think it's a good approach. You quickly get actually working software (which is the most important goal IMHO - there's no sense in perfect software which will never be finished) and gradually make it better. You may have to rewrite it one or two times, but that's actually good since you already have experience then – so you know what you shouldn't do this time etc.





