Nachdem ich nun leider seit einiger Zeit – größtenteils arbeitsbedingt – nicht mehr dazu gekommen bin, neue Beiträge zu schreiben, möchte ich zumindest das Jahr noch vernünftig ausklingen lassen und allen Lesern einen guten Rutsch wünschen. Sobald es was neues zu lesen gibt, findet ihr es hier 😉
[FLOW3] Wie lege ich eine Catchall / Wildcard Route an?
Tragt einfach in eurer Routes.yaml folgendes ein:
- name: 'default' uriPattern: '({all})' defaults: '@package': '[dein_Vendor].[dein_Package]' '@controller': 'Standard' '@action': 'index' '@format': 'html'
Bitte beachten: dieser Routeneintrag sollte der allerletzte sein (also ganz unten stehen), da sonst alle danach folgenden definierten Routen nicht mehr funktionieren werden.
[Quicktip] git per Samba Share zeigt alle Dateien als “geändert” an
Nehmen wir folgende Konstellation: Du hast einen Linux Server, der einen Ordner per SMB (Samba, Windows Freigabe) Share freigibt, in dem sich git Repositories befinden. Greifst du nun von einem anderen Rechner auf diese Dateien zu, so wird git alle Dateien innerhalb dieses Repositories als geändert anzeigen. Ein git diff zeigt dann z.B. folgendes:
old mode 100644 new mode 100755
Dies bedeutet nichts anderes, als dass sich die Zugriffsrechte der Dateien geändert haben. Innerhalb der Samba Share Konfiguration kann man diese Rechte (also Zugriff für Benutzer, Gruppe, Alle) regeln. In vielen Fällen wird sich diese Konfiguration von der in git eingecheckten unterscheiden. Um das Problem zu umgehen, gibt es nun folgende Möglichkeiten:
– im Samba Share Config File die Dateirechte korrekt setzen
– innerhalb des git Repositories folgenden Parameter setzen bzw. umstellen:
git config core.filemode false
Bitte beachten: Wenn dieser Parameter gesetzt wird, kann man KEINE Änderungen von Dateirechten in git committen!
Wollt ihr dies auf eurem Rechner global für alle Repositories machen, dann verwendet folgenden Befehl:
git config --global core.filemode false
Bitte hier besonders daran denken, dass nun in ALLEN git Repositories, auf die dieser Rechner zugreift, kein Committen von Änderungen an den Dateirechten möglich ist – es sei denn, der Parameter wird in einzelnen Repositories explizit überschrieben.
Die schönste und zugleich sinnlose unendliche Maschine
[Quicktip] SSH Key zu Github per Shell hinzufügen
Für alle, die sich unnötige manuelle Schritte beim Hinzufügen eines neuen SSH Keys zum eigenen Github Account sparen wollen:
mit
curl --data "{\"title\": \"NAME\",\"key\": \"`cat ~/.ssh/id_rsa.pub`\"}" --request POST https://api.github.com/user/keys --user "USERNAME:PW"
wird automatisch der Public SSH Key des aktuellen Benutzers im Github Account hinterlegt.
Unter NAME wird ein eindeutiger Name für den Schlüssel angegeben, USERNAME und PW sollten selbsterklärend sein.
Noch ein kleiner Tipp am Rand: bestehende Keys werden weder überschrieben, noch doppelt hinzugefügt.
[Quicktip] Wenn das remote git repository keinen Push annehmen will…
Erinnerung an mich selbst: wenn mich ein remote git Repo das nächste mal mit so einer Fehlermeldung begrüßt
fatal: failed to write object error: unpack failed: unpack-objects abnormal exit Auto packing the repository for optimum performance. fatal: Unable to create '/[reponame].git/packed-refs.lock': Permission denied
…dann macht es Sinn zu prüfen, ob der jeweilige User auf dem Zielserver überhaupt die entsprechenden Schreibrechte für den Repository Ordner hat…
[FLOW3] Wie schreibt man einen eigenen Translation Provider?
Ein weiterer Teil, welcher in der FLOW3 Dokumentation so gut wie gar nicht abgedeckt wird, ist die Frage, wie man einen eigenen Translation Provider implementiert. FLOW3 selbst bringt nur einen Xliff Provider mit. Dieses Format ist der Standard in der Internationalisierung. Allerdings braucht man vielleicht nicht immer ein so aufgeblähtes Format und möchte einfach eine CSV Datei mit 1:1 Übersetzungen hinterlegen. Dafür sind folgende Schritte nötig:
Zuerst legen wir eine neue Klasse im Pfad “[PackageName]/I18n/TranslationProvider/CsvTranslationProvider.php” und folgendem Inhalt an:
namespace [Vendor]\[Package_Name]\I18n\TranslationProvider; use TYPO3\FLOW3\I18n\TranslationProvider\TranslationProviderInterface; /** * The concrete implementation of TranslationProviderInterface which uses CSV * * @FLOW3\Scope("singleton") */ class CsvTranslationProvider implements TranslationProviderInterface { }
Da wir das TranslationProviderInterface implementieren, müssen natürlich auch die entsprechenden Methoden vorhanden sein. Diese sind die “getTranslationByOriginalLabel” und “getTranslationById”. An dieser Stelle bekommt man mit den Parametern “$originalLabel” bzw. “$labelId” das zu übersetzende Label und mit der “$locale” die entsprechend aktuell eingestellte Sprache. Zusätzlich kommen noch ein paar weitere Parameter mit, die aber für eine einfache Übersetzung per CSV nicht zwingend nötig sind. Eine Hilfsmethode, die man dann von beiden Methoden aus aufrufen kann, könnte folgendermaßen aussehen:
private function translate($key, $locale) { $translations = array(); $language = $locale->getLanguage(); if (($handle = fopen([PFAD_ZUR_CSV_DATEI], "r")) !== FALSE) { $translations[$language] = array(); while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { if(count($data) == 2) { $translations[$language][$data[0]] = $data[1]; } } fclose($handle); } $translation = $key; if(array_key_exists($key, $this->translations[$language])) { $translation = $this->translations[$language][$key]; } return $translation; }
Diese Methode ist nur für diesen Beitrag beispielhaft implementiert. Natürlich sollte nicht bei jeder einzelnen Übersetzung die komplette CSV Datei in den Speicher gelesen werden. Also bitte nicht produktiv einsetzen 😉
Anschließend registriert man in der Datei “/Packages/[PackageName]/Configuration/Objects.yaml” den Provider für den I18n Translation Service:
TYPO3\FLOW3\I18n\Translator: properties: translationProvider: object: [Vendor]\[Package_Name]\I18n\TranslationProvider\CsvTranslationProvider
Die CSV Datei hat dann folgenden Inhalt:
Translation;Übersetzung
Sobald man diese Schritte erledigt hat, kann man in allen Fluid Templates mit dem Tag “<f:translate>Translation</f:translate>” Wörter automatisiert übersetzen lassen. Ist für das Wort keine Übersetzung vorhanden, so wird einfach das unübersetzte Wort verwendet.
[FLOW3] Wie kann man mittels Repository eine einfache Count Abfrage durchführen?
Der ORM Teil von FLOW3 besteht leider (zumindest für erfahrene Entwickler) aus sehr viel Magic, die man nicht immer so leicht durchschauen kann. So ist es eigentlich selten nötig, irgendeine Methode im Repository zu implementieren. Rein durch das Erben der Basisklasse “\TYPO3\FLOW3\Persistence\Repository” erhält man die magischen findBy*() und findAll() Methoden, mit denen man so gut wie alle notwendigen Abfragen abdeckt. Nicht so wirklich bekannt sind jedoch die parallel dazu verfügbaren countBy*() und countAll() Methoden, mit denen man allerdings keine Datenobjekte abfragt, sondern eben die Anzahl der möglichen Datensätze als Ergebnis bekommt.
Beispiel:
$userFromDresdenCount = $userRepo->countByWohnort('Dresden');
oder
$userCount = $userRepo->countAll();
Ein schönerer Desktop
Und hier mal wieder ein Artikel von meinem ehemaligen Kollegen Alberto, dieses mal zum Thema Desktop Verschönerung auf dem Mac…
Die meisten Mac Desktops sehen eher langweilig aus und weichen kaum vom Standard ab. Wer nicht ganz im Einheitsgrau versinken will, hat immerhin ein spannendes Hintergrundbild. Eine Vielfalt wie gemodete Desktops unter Windows vermisst man jedoch auf den meisten Macs. Dabei gibt es mit dem GeekTool im AppStore durchaus ein mächtiges, zudem kostenloses Werkzeug, um den eigenen Hintergrund zum Leben zu erwecken. Am Beispiel meines eigenen Desktops möchte ich euch demonstrieren, was möglich ist – mit ein paar Zeilen Bash und dem GeekTool.
Der richtige Hintergrund
Alles steht und fällt mit dem richtigem Hintergrundbild, dieses bildet die Basis für unseren lebendigen Desktop. Ich habe mich hierbei für Vaporware 2.0 von http://browse.deviantart.com/?q=aurahack#/d1kj7zb entschieden, da ich ein großer Fan der 8Bit Kunst und ebenso Musikliebhaber bin. Kleiner Bonus: das Bild gibt es auch in einer hohen Auflösung und eignet sich damit Perfekt für mein Retinadisplay.
Typhographie
Die Magie dieses Desktops ist vor allem den Ausgaben der verschiedenen Shellscripte geschuldet. So ist eine entsprechend passende Schrift unerlässlich, wenn man sich die Wirkung nicht durch eine 08/15 Standardschrift zerstören will. Aufgrund des 8Bit Themas des Hintergrundbildes sollte die Schrift auch ein wenig pixelig, eben 8Bit Style sein. Fündig geworden bin ich hier mit dem 8Bit Wonder, welches für alle Ausgaben verwendet wird. Die Farbwahl für die Ausgaben fiehl dabei auf weiß, da dies beim gewählten Hintergrund den besten Kontrast ergibt.
Die Magie
Bis hierher haben wir nur ein gut aussehendes Hintergrundbild – aber das haben viele. Wir wollen mehr. Wir wollen den ultimativen Hintergrund. Um das zu ermöglichen, brauchen wir ein paar Scripte, die wir mittels GeekTool ausführen und richtig auf dem Desktop platzieren.
CPU- und Arbeitsspeicherverbrauch
Beginnen wir in der rechten, oberen Ecke. Wäre es nicht toll, hier den aktuellen Arbeitsspeicherverbrauch und die genutzte CPU im Blick behalten zu können? Hierfür müssen wir einfach ein Shell geeklet aus dem gestarteten GeekTool auf die richtige Stelle auf dem Desktop ziehen und in den Einstellungen das Command Feld mit dem unten stehenden Script befüllen. Dieses liest die CPU Load mithilfe von top aus und formatiert diese als Balkendiagramm mit entsprechender Prozentanzeige. Selbiges wird für den Arbeitsspeicher durchgeführt, nur, dass sowohl Werte für den genutzten und ungenutzten Speicher ausgelesen werden. Damit wir immer aktuell bleiben, sollte die refresh time auf 0.1 Sekunden gesetzt werden. (Anm. Bytelude: bei solch kurzen Refresh-Zyklen immer die CPU und den Akkuverbrauch im Auge behalten – im Zweifel lieber längere Refresh-Raten verwenden)
myCPU=`top -l 1 | awk '/CPU usage/ {print $3}' | sed s/%//`
myCPU=`echo "tmp=$myCPU; tmp /= 1; tmp" | bc`
typeset -i b=9
echo "CPU Usage \c"
while [ $b -lt $myCPU ]
do
echo "33[1;37m▇33[0m\c"
b=`expr $b + 10`
done
#echo "33[1;39m█33[0m\c"
while [ $b -lt 99 ]
do
echo "33[2;30m▇33[0m\c"
b=`expr $b + 10`
done
echo " $myCPU%\c"
echo "\r"
unset myCPU
unset b
myUsedMem=`top -l 1 | awk '/PhysMem/ {print $8}' | sed s/M// `
myFreeMem=`top -l 1 | awk '/PhysMem/ {print $10}' | sed s/M// `
myActiveMem=`top -l 1 | awk '/PhysMem/ {print $4}' | sed s/M// `
myTotalMem=` expr $myUsedMem + $myFreeMem`
myUsedPer=`echo |awk '{print f / t * 100}' f=$myActiveMem t=$myTotalMem`
myUsedPer=`echo "tmp=$myUsedPer; tmp /= 1; tmp" | bc`
typeset -i c=9
echo "Memory Usage \c"
while [ $c -lt $myUsedPer ]
do
echo "33[1;37m▇33[0m\c"
c=`expr $c + 10`
done
#echo "33[1;39m█33[0m\c"
while [ $c -lt 99 ]
do
echo "33[2;30m▇33[0m\c"
c=`expr $c + 10`
done
echo " $myUsedPer%\c"
echo "\r"
unset myUsedMem
unset myFreeMem
unset myTotalMem
unset myUsedPer
unset c
unset count
unset i
unset currname
unset currp
unset a
Dienste im Blick behalten
Als Webentwickler kann man nicht ohne seinen Apache und seine MySQL Datenbank entwickeln. Warum also nicht den Status dieser beiden Dienste im Blick behalten und sofort sehen, ob diese laufen oder gerade offline sind? Selbstverständlich kann hiermit auch jeder andere Dienst im Auge behalten werden, solange dessen Prozessname bekannt ist. Hierfür wird, wie im vorherigen Beispiel, ebenfalls ein Shell geeklet benötigt, welches unten stehendes Script als Command mit bekommt. Dieses durchsucht den Prozessbaum, angezeigt durch ps, nach dem gewünschten Prozess. Wenn dieser gefunden wird, so wird in grün running ausgegeben, ansonsten in rot gestaltet ein offline. Gekapselt ist das ganze in eine Bashfunktion, welche mit echo ausgegeben wird. Auch hierbei sollte die refresh time des geeklets nicht außer acht gelassen werden, jedoch reichen hier auch größere Sekundenwerte.
typeset -i show=0 function service() { echo $1 | tr '[:lower:]' '[:upper:]' if ["$(ps -Ac | grep $1)" != "" ] then echo "33[1;32m running 33[0m else echo "33[1;31m offline 33[0m fi }
echo $(service httpd) echo $(service mysqld)
Wer bin ich?
Manchmal gibt es diesen Moment, da fragt man sich: wer bin ich, woher komm ich, wohin gehe ich. Als ITler folgt darauf meist die Frage nach der eigenen IP als zentraler Lebenspunkt – also warum diese nicht ebenfalls immer in Sicht haben? Auch dafür können wir wieder ein Shell geeklet nutzen, welches per curl die eigene externe IP beim DNS-Provider dyndns.org erfragt und aus der Rückgabe per sed alle Zeichen außer Zahlen und Punkten entfernt, da um die eigentliche IP herum etliche HTML-Tags liegen. Das fertige Script sollte danach wie folgt aussehen:
echo External IP: `curl -s http://checkip.dyndns.org/ | sed 's/[a-zA-Z/ :]//g'`
Hier spielt die Musik!
Da die letzten paar Scripts alle technischer Natur waren und wohl nicht für jeden Nutzer das richtige bieten, sollen nun auch ein paar Informationen angezeigt werden, die nicht nur technikaffinen Menschen etwas bringen. Und da (fast) jeder Musik mag: warum nicht einfach den aktuellen Titel mit Interpreten und zugehörigem Album anzeigen, sofern iTunes gerade läuft? Passt ja auch ganz gut zum gewählten Hintergrund. Glücklicherweise hat iTunes seit einiger Zeit eine Script Schnittstelle, welche per AppleScript abgefragt werden kann und entsprechende Informationen bereit stellt. Da GeekTool aber AppleScripts nicht direkt ausführen kann, lohnt es sich einen Blick auf das Kommando osascript zu werfen, welches nichts anderes tut, als ein übergebenes AppleScript auszuführen und die Rückgabe auszugeben. Mithilfe des Parameters -e kann hier auch eine Zeichenkette als Script übergeben werden und es muss kein zusätzliches Script auf einer nie wieder auffindbaren Stelle im System hinterlassen werden. Unten stehendes Script tut dann nichts weiter als sich alle Prozesse mit ihrem Namen vom System zu holen, diese nach iTunes zu durchsuchen und im Fehlerfall, wenn iTunes also nicht läuft, die Ausgabe auf Stopped zu setzten. Wenn iTunes jedoch gerade läuft holt das Script sich Titel, Album und Interpret des gespielten Lieds und schreibt diese auf den Outputstream. Ein kleiner Trick hierbei sind die new_line Tags, welche als Trennzeichen genutzt werden, um die drei Attribute später untereinander ausgeben zu können. Die Ausgabe geschieht dabei mit einem echo, welches nach awk gepipet wird. Awk kümmert sich darum, dass anhand des new_line Tags die Ausgabe zerlegt und nur der gerade relevante Teil ausgegeben wird. Das fertige Script sieht dann wie folgt aus und kann direkt in einem Shell geeklet laufen gelassen werden:
DATA=$(osascript -e 'tell application "System Events"
set myList to (name of every process)
end tell
if myList contains "iTunes" then
tell application "iTunes"
if player state is stopped then
set output to "Stopped"
else
set trackname to name of current track
set artistname to artist of current track
set albumname to album of current track
set output to trackname & "new_line" & artistname & "new_line" & albumname
end if
end tell
else
set output to "Enjoy the silence"
end if')
echo $DATA | awk -F new_line '{print $1}'
echo $DATA | awk -F new_line '{print $2}'
echo $DATA | awk -F new_line '{print $3}'
Mehr Text
Viel Musik lebt von ihren Lyrics, also zeigen wir diese auch gleich noch mit an. Zumal auf dem Hintergrundbild noch einiges an Platz frei ist, der sonst so leer wirkt. Das folgende Script ist im Grunde genommen nicht viel anders als das vorherige, jedoch wird diesmal nur per AppleScript der Liedtext zum aktuellen Song abgefragt. Sollte iTunes nicht laufen, so wird hier nur ein leerer String zurück gegeben. In der Ausgabe werden alle Vorkommen von “\r” durch “\n” ersetzt, damit diese Umbrüche korrekt umgesetzt werden.
echo "\n\n"
osascript -e 'tell application "iTunes" to lyrics of current track' | tr '\r' '\n'
Zeit ist Geld
Als nächstes sollten wir einen Blick auf den Gameboy in der rechten, unteren Ecke werfen, welcher bisher nichts anzeigt. Das soll sich ändern. Um auch mal ein einfaches Script zu nutzen soll hier nur mit Hilfe des date Kommandos das aktuelle Datum, sowie die Uhrzeit angezeigt werden. Hierzu gibt es nicht viel zu sagen, dem date Kommando wird als Argument mitgegeben, wie das Datum, respektive die Zeit aussehen soll, weitere Optionen hierzu sind in der entsprechenden Manpage nach zu lesen.
date +%d.%m.%y
date +%H:%M
Alle Farben sind schön
Um auch mal eine aufwändigere Kombination von mehreren geeklets zu zeigen und ein wenig Farbe ins Spiel zu bringen, soll unser aktueller Speicherverbrauch in einem Tortendiagramm visualisiert werden, welches die Kopfhörer des Hintergrundbildes überlagert. Dafür brauchen wir zwei geeklets: ein Shell geeklet zum Sammeln der Daten und Generieren der Grafik sowie ein Bild geeklet zum Anzeigen der generierten Grafik. Das Sammeln der Daten geschiet im Grunde genommen durch das Auslesen der Prozessliste mit ps und umformartieren dieser Informationen per cut, sed, awk und anderen UNIX Tools. Hier in die Tiefe zu gehen würde nur unnötig ausarten. Die gesammelten Daten werden danach mit Hilfe der Google Chart API zu einer ansehnlichen Grafik aufbereitet, welche per curl im temporären Ordner abgelegt wird.
SIZE="450x650"
TYPE="pc"
COLOR="E5707070|C5606050|C5A5A050|AAAAFF50|AAAAFF30,E5AB77|F5CB97"
BG="bg,s,00000000"
ps Amo pmem,comm | grep -v % | sed 's/\/.*\///; s/^ //; s/,/\./' > /tmp/memusage.log
grep -v "0\." /tmp/memusage.log > /tmp/memusage2.log
(grep "0\." /tmp/memusage.log | cut -d\ -f1 | paste -sd+ - | bc; echo others) | xargs >> /tmp/memusage2.log
data=`cut -d\ -f1 /tmp/memusage2.log | paste -sd, -`
unused=`echo $data -100 | sed 's/,/\+/g' | bc`
legend=`cut -d\ -f2,3,4,5 /tmp/memusage2.log | sed 's/ /%20/g' | paste -sd\| -`
sum=`vm_stat | head -6 | tail -5 | awk 'BEGIN{sum = 0;} {sub(/\.*$/,""); sum+=$NF} END{print sum}'`
vm_stat | head -6 | tail -5 | awk -F: '//{print $1, 100*$2/'$sum'}' | sed 's/down //; s/,/\./' | cut -d\ -f2,3 > /tmp/memusage3.log
pfree=`grep free /tmp/memusage3.log | cut -d\ -f2`
pinactive=`grep inactive /tmp/memusage3.log | cut -d\ -f2`
pactive=`grep "^active" /tmp/memusage3.log | cut -d\ -f2`
pspeculative=`grep speculative /tmp/memusage3.log | cut -d\ -f2`
pwired=`grep wired /tmp/memusage3.log | cut -d\ -f2`
pmem="$pwired,$pactive,$pinactive,$pspeculative,$pfree"
plab="wired|active|inactive|cache|free"
rm /tmp/memusage.log
rm /tmp/memusage2.log
rm /tmp/memusage3.log
link="http://chart.apis.google.com/chart?cht=$TYPE&chs=$SIZE&chd=t:$pmem|$data,$unused&chco=$COLOR&chf=$BG&chl=$plab|$legend|"
echo $link
So viel zum schwierigen Teil, denn sobald das Bild generiert wurde, muss es nur noch mit Hilfe eines Bild-geeklets angezeigt werden. Mit 230 Pixeln Höhe und Länge ist das geeklet optimal dimensioniert und überdeckt genau die Kopfhörer. Als weitere Eigenschaften müssen neben der schon bekannten refresh time, denn dieses Bild soll alle paar Sekunden neu generiert werden, auch die Bildurl angegeben werden. Hierbei kann per file:///tmp/memusage.png auf das eben generierte Bild zruück gegriffen werden. Um die Infos aktuell zu halten, sollten beide geeklets eine kurze refresh time bekommen.
Wenn auch diese beiden geeklets funktionieren, ist die Arbeit erstmal getan. Jedoch gibt es noch viel zu entdecken und mit Hilfe des MacOSX Unix Unterbaus gibt es noch viele weitere Möglichkeiten, verschiedenste Informationen abzurufen und diese auf dem Desktop darzustellen. Hier kann sich ruhig ausgetobt werden, um die perfekte Balance zwischen nützlicher Datenvisualisierung und optisch ansprechendem Desktop zu finden.
[Infografik] Die Evolution des iPhones
via apfeltheater.ch