Photos auf Google Maps

Seit iPhoto mit “Photos” generalüberholt wurde ist die Kartenübersicht mit GPS Koordinaten sehr schlecht geworden.

Informationen werden beim Zoom verschluckt, die Karte ist entweder winzig klein oder nur ein Subset aus allen Bildern.

exiftool

Die wundervolle Software exiftool lässt Meta Daten aus Bildern lesen und schreiben. Mit folgender Zeile werden für alle Bilder die GPS Längen- und Breitengrade in Dezimalkodierung ausgegeben.

exiftool -gpslongitude -gpslatitude -n -T /Users/noqqe/Pictures/Photos\ Library.photoslibrary/Masters/ -r

Google Maps

Bisher hab ich nur die Koordinaten. Wie ich die in Google Maps reinfülle, hab ich per Stackoverflow herausgefunden

Koordinaten konvertieren

Ich muss also

7.42793055555556 43.7407694444444

zu

["Bild", 43.7370305555556, 7.42133888888889, 3598],

konvertieren. Wobei es aber zwingend erforderlich ist, dass die letzte ID eindeutig und von 1 an fortlaufend ist. Diese zwei Zeilen bewerkstelligen den ganzen Arbeitsablauf.

$ exiftool -gpslongitude -gpslatitude -n -T /Users/noqqe/Pictures/Photos\ Library.photoslibrary/Masters/ -r  | uniq | awk '{print $2" "$1}' > /tmp/foo

$ grep -v -- "- -" /tmp/foo | gsed -e 's/\s/, /' -e 's/^/["Bild", /' | gawk '{print $0 ", " FNR "],"}'']'

Danach hab ich einfach alles in das File aus Stackoverflow pastiert und fertig. maps.html im Browser aufgerufen.

Allgemein gefragt, gibt es eine self-Hosted, Webinterface Anwendung für Fotos die Gesichtserkennung, ACLs und Kartenvisualisierung kann? Ich will sowas.

Ansible - Mein neues Pssh

pssh

pssh war für eine Menge Tätigkeiten lange Tool der Wahl. Deployments, Services restarten, Files verteilen, User löschen, Hotfixes usw.

pssh -h ~/Code/mongoserver.txt -l root -t 350 -i "/etc/init.d/mongodb restart"

Der Nachteil ist aber allerdings, dass bei pssh Listen mit Hostnamen in Form von Files gepflegt werden müssen. Das wird schnell unübersichtlich und aufwändig.

Ansible Hosts

Deshalb bin ich vor ca. einem Monat zu Ansible gewechselt. Vorrangig wegen des Host-Matchings.

[mongodb]
mongodb01.example.org
mongodb02.example.org
mongodb03.example.org

[li]
li-jmp-prod
li-jmp-dev
li-jmp-stage

[n0q]
noc.n0q.org ansible_python_interpreter=/usr/local/bin/python
aax.n0q.org ansible_python_interpreter=/usr/local/bin/python

[work:children]
li
mongodb

Hosts in diesem File können mit Regex, Excludes und Gruppen von Ansible aus direkt angesprochen werden. Auch Gruppen die andere Gruppen enthalten sind möglich. Für Details hier.

Ansible als pssh Ersatz

Auch wenn ich ansible nicht so nutze wie die Meisten (nämlich als full-blown Config Management) so ist es doch extrem handlich.

Zum Beispiel einen User auf allen Servern der Gruppe “work” löschen

ansible work -m user -a 'name=alice state=absent remove=yes'

Wie oben im Beispiel alle MongoDB Prozesse neustarten

ansible mongodb -m service -a 'name=puppet state=restarted'
ansible mongodb -m service -a 'name=mongodb state=restarted'

Oder einen nrpe-Check mittels Shell Command bearbeiten:

ansible n0q -m shell -a 'sed -i "s#plugins/check_mem#plugins/check_mem -C#" /etc/nrpe.cfg'

Oder ein bestimmtes File von allen angegebenen Hosts herunterladen

ansible n0q -m fetch -a 'src=/etc/bashrc dest=/tmp/fetched'

Es fühlt sich ein bisschen an, wie die UNIX-API für alles was man so braucht.

Tarsnap Backups einer alten Maschine löschen

Seit einiger Zeit verwende ich tarsnap als Backup auf meinen VMs. Die Crypto, der Preis, das System. Gefällt mir. Nun habe ich vor ein paar Wochen ein Stück Hardware gegen eine kleine VM ausgetauscht. Die Backups auf Tarsnap habe ich vorher noch nicht gelöscht.

Da die Maschine nicht mehr existent ist, die Backups aber maschinen-gebunden, muss ich diese noch loswerden um nicht jeden Monat dafür mit zuzahlen. Nicht dass es sonderlich teuer wäre, aber trotzdem.

Dafür erforderlich ist natürlich der Key der Maschine.

Die Config erzeugen ist der erste Schritt.

cachedir /tmp/tarsnapc
keyfile /tmp/key
humanize-numbers
print-stats
totals
normalmem

Danach ein mkdir /tmp/tarnsapc und den Key nach /tmp/key kopieren. Bevor das eigentliche löschen losgeht, muss das Cacheverzeichnis mit den Metadaten befüllt werden:

$ tarsnap --config conf --fsck
Phase 1: Verifying metadata validity
Phase 2: Verifying metadata/metaindex consistency
Phase 3: Reading chunk list
Phase 4: Verifying archive completeness
  Archive 1/56...
  Archive 2/56...
  Archive 3/56...
  [...]
  Archive 56/56...
Phase 5: Identifying unreferenced chunks

Jetzt können die Backups des alten Servers die sich noch bei Tarsnap befinden angeschaut werden.

$ tarsnap --config conf --list-archives
20150402-001026-daily-/home
20150404-001026-daily-/home
20150316-001024-weekly-/etc
20150401-001024-monthly-/etc
20150330-001026-weekly-/root
[...]

Um die Backups zu entfernen, eine einfache for-Loop über alle gefundenen

for x in $(tarsnap --config conf --list-archives); do
  tarsnap --config conf -d -f $x
done

Geld gespart.

MongoDB KeyFile

Hatte gerade ordentlich Spass. Spontan eine MongoDB mit KeyFile und Auth aufgesetzt. So ein KeyFile ist eigentlich nur Random Content, der auf jeder Instanz gleich sein muss, um sicherzustellen das sich keine fremde Instanz einfach so in das MongoDB Cluster hineinschummelt.

  • “Ey, das kann ja einfach jeder lesen. Nö”
  • “Jetzt kann ich’s nicht mehr lesen… -.-”
  • “Ich kann’s öffnen, verstehe den Inhalt aber nicht..”
  • “LOL TLDR;”

Hat irgendwie was von “Nein, Doch, Ohhh”.

Mehr Commandline Wiki

Wenn ich nicht gerade mit IRC-Bot schreiben oder das Wiki für k4cg.org schön/neu mache, bastle ich immer wieder an cmddocs.

Der Code wurde umfangreicher, robuster, paar Features kamen hinzu. Tollste Sache ist aber, dass ich mal was auf pypi hoch geladen hab. Das ist tatsächlich das erste Packet was ich dort hochlade. Demnach kann man cmddocs jetzt einfach über pip installieren.

$ pip install cmddocs
$ cmddocs

\o/, Extrem fragwürdig finde ich aber die Downloads/Zugriffszahlen.

So schön ich es fände wenn es so wäre, aber das kann einfach nicht sein. Wenn jemand nen Link hat wie diese Stats generiert werden oder eine Erklärung hat (Bots, Mirrors?) bitte, her damit.

Wesentlichste Änderung ist wahrscheinlich, dass Markdown->ANSI Highlightning jetzt nicht mehr nur über 4 Zeilen Regex realisiert ist. Ich hab den Markdown Lexer von mistune verwendet und die Output-Funktionen so überschrieben, dass statt HTML ANSI Codes herauskommen.

class md_to_ascii(mistune.Renderer):

    # Pagelayout
    def block_code(self, code, lang):
        return '\n\033[92m%s\033[0m\n' % code.strip()
    def header(self, text, level, raw=None):
        if level == 2 or level == 1:
            head = '\n\033[4m\033[1m\033[37m%s\033[0m\n' % text.strip()
        else:
            head = '\n\033[1m\033[37m%s\033[0m\n' % text.strip()
        return head
    def block_quote(self, text):
        return '\n%s\n' % text.strip()
    def block_html(self, html):
        return '\n%s\n' % html.strip()
    def hrule(self):
        return '---'
    def list(self, body, ordered=True):
        return '\n%s' % body
    def list_item(self, text):
        return '* %s \n'  %  text.strip()

Schönen dank an Flowwar für die Idee an der Stelle ;) Ansonsten noch folgende Dinge eingebaut:

  • undo Feature implementiert
  • Suchfunktion gibt auch Ergebnisse in Dateinamen wieder (siehe Screenshot oben)
  • Anständige Fehlermeldungen an mehreren Stellen
  • Nicht vorhandene Configoptionen mit sinnvollen Defaults eingebaut
  • Error Handling für nicht vorhandene Config/Datadir
  • Description für pip eingefügt
  • Readme nach RST konvertiert
  • Promptfarbe konfigurierbar

Wems gefällt und Pull- oder Feature Requests hat, bitte immer her damit.

Dinge die ich bediene.

Ich glaube ich habe mich noch niemals bzgl. meiner privaten Situation mit Technik so wohl gefühlt wie bisher. Das Equipment, das OS. Macht Spaß und funktioniert.

Ein bisschen wie bei usesthis.com (wtf, wie langweilig ist bitte das Setup von Bruce Schneier?) beschreibe ich mal was ich so benutze.

MacBook Pro 13”

Seit Ende 2014 benutze ich ein MacBook. Mein Zweites. Zwischenzeitlich hatte ich ein Lenovo Thinkpad x201 was zwar seitens der Hardware super geil war, mir aber das mit dem Betriebssystem und alles zum Hals raushing. Hatte ich schon erwähnt das 2015 das Jahr von Linux auf dem Desktop ist?

All diese Dinge die bei OS X einfach so angenehm sind. Safari synchronisiert einfach alles zwischen iPhone und anderen MacBooks hin und her. Airmail2 als Mailclient ist großartig. Die Kalender & Adressbuch Synchronisation rockt. Nutze 1Password, Spotify und seit dem Switch von iPhoto zu Photos kann man das auch wieder benutzen. Ich mag es sehr wie alles sich integriert, funktioniert und man eigentlich nie irgendwas tun muss. Ganz besonders toll: Die iMessage/SMS/FaceTime vom Handy zum OS. Ich hätte nie gedacht, dass ich das so intensiv benutze. Mit iMessage beweist Apple auch noch, dass benutzerfreundliche Crypto nicht unmöglich ist. Die Meisten wissen es nichteinmal.

Genug Kuschelkurs, OS X Liebesschwüre gibts schon genug im Netz. Die uralte Software z.B. rsync oder OpenSSH ist ein echtes Unding. Auch iTunes. Ich benutze es einfach nicht. Es fehlt mir nicht.

OpenBSD CLI VM

Ich habe es mir angewöhnt alles was ich so für den Alltag brauche auf einer klein dimensionierten VM irgendwo im Internet zu hosten.

Das ist extrem praktisch, da ich egal wo ich bin, egal an welchem Rechner ich sitze immer alles da habe. Software die ich dort auf dem bei rootbsd gehosteten System nutze ist unter Anderem:

Auf der Maschine befindet sich sonst nichts. Alles läuft unter meinem User, kein Daemon der lauscht, nichts. Gesichert wird die Kiste mittels tarsnap

Klar hat das auch Nachteile, ich kann auf meine Todoliste nicht zugreifen wenn ich nur mit dem iPhone bestückt im Supermarkt stehe, aber diesen Use-Case habe ich auch einfach nicht. Mit newsbeuter Urls im Browser öffnen ist auch bescheiden, daher muss ich dort immer klicken. Wenn jemand hierfür eine Lösung hat, immer her damit.

OpenBSD Server

Der Normal-Nerd hat natürlich auch Bedürfnisse Dinge zu hosten. Deshalb gibts eine zweite Maschine, die alle meine Dienste bereitstellt die ich so brauche, diverse PHP/MySQL Applikationen für den Eigengebrauch.

OpenBSD, brauche ich jetzt nicht erwähnen, ist dafür momentan so mein liebstes OS. Sicher per default. Die Devs hauen immer wieder allerhand nützliche Sachen wie lustiges Crypto für Ping oder seit neuestem privilege separated file

  • Meine privaten git Repos mit gitolite
  • der Blog
  • Zwei Instanzen von nichtparasoup
  • Isso Kommentarsystem
  • MongoDB
  • und diverse andere Websites

Demnächst kommst vielleicht noch etwas DNS hinzu, was ich dort hoste.

Dinge die mich Nerven gibt es auch hier. Nämlich die fehlende SNI Funktionalität bei httpd, relayd und libTLS. Somit muss ich bisher noch nginx für die Websites nutzen. Aber das ist nur eine Frage der Zeit.

Weechat Copy & Paste

Etwas aus vim mit Tagbar oder mutt mit Sidebarpatch kopieren ist halt immer irgendwie kacke. Bei weechat gibts das gleiche Problem mit dem buffers Plugin und der nicklist.

Kreuz und quer Pipes und nicks drin. Nervt. Deshalb hier zwei kleine Aliases, die ich mir gebastelt hab.

/alias hidebars /bar hide nicklist ; /bar hide buffers
/alias showbars /bar show nicklist ; /bar show buffers

So ist’s für mich am Einfachsten irgendwelches Zeugs aus IRC zu kopieren.

  • /hidebars
  • Copy
  • /showbars

Hugo Templating und Themes

Ein bisschen Hands-On an meine neue Blogging Engine. Bevor ich den Blog migrieren konnte fehlten noch einige Anpassungen am Theme.

Da keines der Themes mir Out-of-the-Box gefallen hat, musste ich das Hyde Theme ziemlich aufbohren.

Pagination

Pages. Alle Blogposts auf der Startseite laden ist echt ungünstig. Pagination ist allerdings ziemlich gut dokumentiert.

  <div class="posts">

    {{ $paginator := .Paginate (where .Data.Pages "Type" "post") }}
    {{ range $paginator.Pages }}

    <div class="post">
      <h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
      <span class="post-date">{{ .Date.Format "2006-01-02" }}</span>
      {{ .Content }}
    </div>

    {{ end }}
  </div>

  {{ partial "pagination.html" $paginator }}

Kurz gesagt, Variable $paginator mit Content befüllen und mit range drüber integrieren. Paginate greift dabei auf die Variablen aus der Config zurück.

$ cat config.yaml
paginate: 10
paginatePath: "page"

Danach kann man durch die Seiten pagen.

Das komplette Fils gibts auf github

Archive Page

Damit man aber trotzdem nicht alle Seiten einzeln durchkramen muss, fand ich ‘ne Archivseite auf Blogs schon immer sinnvoll. Gerade wenn die Site an sich statisch ist und es somit keine Suche gibt.

Was man im Endeffekt erreichen möchte ist also eine statische Seite erzeugen, die kein Blogpost und aber zur Build-Zeit dynamischen Content hat.

Pages können dazu konfiguriert werden einem bestimmten Typ zu entsprechen.

$ hugo new archives.md
$ vim content/archives.md
---
date: "2012-03-31T21:38:03+02:00"
draft: false
title: "Archives"
type: archives
url: "/archives/"
---

Für den type muss ein Layout gleichen Namens im Theme enthalten sein:

$ tree themes/noqqe/layouts/
themes/noqqe/layouts/
├── 404.html
├── _default
│   ├── list.html
│   └── single.html
├── archives
│   └── single.html
├── index.html
├── page
│   ├── list.html
│   └── single.html
├── partials
│   ├── head.html
│   ├── isso.html
│   ├── pagination.html
│   └── sidebar.html
└── post
    ├── list.html
    └── single.html

Hier erkennt man auch, dass ich neben archives auch noch post und page als Types definiert habe.

Der Single View für das Archiv ist das einzige was benötigt wird.

{{ partial "head.html" . }}
<body class="theme-base-0b">

{{ partial "sidebar.html" . }}

  <div class="content container">
  <div class="post">
  <h1>{{ .Title }}</h1>
      {{ range (where .Site.Pages "Type" "post").GroupByDate "2006"  }}
        <h2>{{ .Key }}</h2>
        <ul>
          {{ range .Pages }}
          <li>
              <span>{{ .Date.Format "02.01" }}</span>
              <a href="{{ .Permalink }}">{{ .Title }}</a>
          </li>
            {{ end }}
        </ul>
      {{ end }}
  </div>
  </div>
</body>
</html>

Im Endeffekt ist die Syntax ziemlich ähnlich wie bei der Pagination. Nur der range-Query ist etwas mehr advanced. Im Endeffekt for-Loop über allen Content mit WHERE und GROUP BY Command.

An dem “2006” nicht stören. Die Templating Engine funktioniert nicht mit wilden %Y-%m-%d Commands, sondern einem Referenz-Datum. Schön sehen kann man das auch hier

Tags und Categories

Was auch gefehlt hat war, dass Tags und Kategorien im Single-View der einzelnen Posts angezeigt werden. In themes/noqqe/layouts/post/single.html:

 <div class="post">
 <h1>{{ .Title }}</h1>
   <span class="post-date">{{ .Date.Format "2006-01-02" }}</span>
   {{ .Content }}

   <span class="meta">Categories:
   {{ range .Params.categories}}
     <a href="/categories/{{ . | urlize }}">{{ . }}</a>
   {{ end }}
   </span>
   <br/>
   <span class="meta">Tags:
   {{ range .Params.tags }}
     <a href="/tags/{{ . | urlize }}">{{ . }}</a>
   {{ end }}
   </span>
 </div>

Genau die Funktion urlize macht dann noch Links aus den Tagnamen.

So schön <3 Macht Spaß

noqqe.de auf GitHub

Wie bereits auf Twitter gesagt, wer möchte darf gerne meine falschen Kommata reparieren und Rechtschreibfehler korrigieren.

Zum Durchsuchen und Wiederverwenden ist der Source auf Github ebenfalls nützlich, schätze ich. <3

Github Repository: github.com/noqqe/noqqe.de

Bookmarks

Seit 2013 benutze ich Pinboard. Letztens flog auf GitHub allerdings ein Commandline Bookmark Manager vorbei. Den Gedanken fand ich eigentlich total toll. Die Syntax fand ich komisch, Ausgabe sah strange aus. Aber es kam auch noch erschwerend hinzu, dass es nicht mal gebaut werden konnte. Also hab ich weiter gesucht und einen ziemlich schönen gefunden.

bm ist in Bash geschrieben, sah schön aus, einfach gestrickt. Eigentlich super. Aber auch hier liess die Bedienung etwas zu wünschen übrig. Aber da das Zeug ja Opensource ist, fork it baby.

bm Fork

Was anfangs nur ein “ja ich passe mir das Teil ein klein bisschen an” war, wurde irgendwie zum Komplettumbau.

  • Der ganze Dropbox Folder Kack ist weg
  • HTML Preview im Browser mit webkit2png ist weg
  • Title wird automatisch mit curl beim adden eines Links hinzugefügt.
  • Syntax zum Bedienen stark umgeschrieben
  • Clean Funktion entfernt
  • Datum (wann wurde der Link geadded) wird automatisch hinzugefügt.
  • Farblich / Formatsmäßig umstrukturiert.

Das Repo: github.com/noqqe/bm

Eine Lizenz würde ich dem ganzen auch gerne hinzufügen, aber da der original Autor noch keine Lizenz hinzugefügt hat, muss ich damit erstmal warten.

Migration von Pinboard

Jetzt musste ich nur noch alle >1000 Bookmarks von Pinboard umziehen. Pinboard bietet einen json Export der eigenen Bookmarks mit allen Meta Informationen an.

Diesen hab ich mir per einfacher Download Funktion lokal gespeichert und mittels dieses Python Schnipsels in das “neue” bm Format umkonvertiert.

import json

with open('dump.json') as dataf:
  data = json.load(dataf)
    for x in data:
      print x["href"]+"|"+x["tags"]+"|"+x["time"]+"|"+x["description"]

Und wenn es beim Umleiten des STDOUT mit Python wegen des Encodings nicht klappt, export PYTHONIOENCODING=utf-8 benutzen. Saugeil. Damit hatte ich immer Probleme.

Ich weiss von ein paar Leuten, dass Sie den RSS Feed meines Pinboard Profils lesen. Für den Moment wird es dort keine neuen Dinge geben. Eventuell bastle ich mich in Python ein kleines Skript dass meine Bookmarks regelmäßig in RSS giesst. Da schau ich aber erstmal.