Schlagwort-Archive: Sed

 – Der Colordaemon war da! – 

colordaemon

Heute geht es mal wieder um Linux. Und nur am Rande um den Colordaemon, ein Daemon, also ein Hintergrundprozess, der sich, wie meist, durch ein kleines D am Namensende verrät. Wobei es auch ein, zwei Dämonen gibt, sich nicht so verraten, und natürlich gibt es Programme, die zufällig auf ‚d‘ enden, ohne dass sie damit signalisieren wollen, dass sie Dämonen sind. Also ein Fall, wie geschaffen, um den Unterschied zwischen starken Indizien von Beweisen zu erläutern, wüssten nicht mehr Leute, was Indizien und Beweise sind, als was Dämonen unter unixoiden Systemen sind.

Andere, mehr oder weniger bekannte Dämonen, sind der Druckerdaemon cupsd des common unix printing service, sowie dbus-daemon, avahi-daemon, die auf andere Weise ihre Dämonenhaftigkeit äußern, aber ich verrate jetzt nicht wie, usb-storage und cron sind wohl auch Dämonen, und haben kein D am Ende. Cron spielt noch eine Rolle am Rande. Dagegen wären sed und thunderbird Programme, die trotz D-Endung keine sind.

Wen’s interessiert, ps ax -o cmd gibt die Namen aller laufenden Prozesse aus.

Das eigentliche Thema hier sind aber weder Dämonen, noch der colord im Besonderen, sondern das syslog, Scheduler und Orage. Ein Scheduler ist ein Zeitplaner und Orage ist der Zeitplaner, um den es hier geht.

Motivation:

Oft wollen Leute, dass das System sie regelmäßig über Dinge informiert, und sie wollen es auf dem Desktop sehen. Dabei treffen sie auf Linuxexperten, die oft beruflich oder ehrenamtlich Sysadmin sind, und für solche Aufgaben die seit den 60ern bewährten Programme cron/anachron benutzen (anacron ist ein anachronististischer cron, habe ich mir sagen lassen), aber diese arbeiten befehlszeilenorientiert und werden über superschlanke, jedoch leicht kryptische Tabellen, die crontabs, konfiguriert – das ist schon nicht jedermanns Sache.

Außerdem laufen sie vom Systemstart weg, noch bevor die grafische Umgebung, X11 und der ganze Desktopkrempel geladen ist und nicht mit den Rechten des Users. Auf Servern läuft meist gar keine Desktopumgebung und folglich sind sie nicht sonderlich dafür ausgelegt, dem User, der womöglich gar nicht angemeldet ist, der auch kein DE (Desktop-Environment) geladen hat, eine Popupnachricht zu senden.

Es gibt dafür Lösungen, und zwar muss man die Xauthority bemühen und 0:0 an das Programm melden, welches um 17:15 aufpoppen soll – da man das so selten macht, hat man die Syntax nicht im Kopf und ist verstimmt. Im Ubuntuusers.de-Wiki ist, unter Fenster öffnet sich nicht, vermerkt wie es geht (noch etwas nach unten scrollen).

Auch ich habe schon oft darauf verwiesen, aber jetzt, bei meiner oberflächlichen Beschäftigung mit Orage eine einfache Alternative gefunden. Und darum geht es hier. :)

Also, wenn man ein Programm, dass die grafische Oberfläche braucht, starten will, dann geht man zu Orage. Hat man oben rechts in der Systemleiste eine Uhr laufen, dann bringt ein Doppelklick darauf wahrscheinlich Orage im Kalendermodus in den Vordergrund.

orage-monat

Was wir jetzt noch brauchen ist aber ein praktisches Beispiel, und deswegen kommen wir einfach nicht auf den Punkt, sondern holen nochmal auf einem zweiten Pfad aus.

Man hat ja unter /var/log/ jede Menge Logdateien liegen, die man nie anschaut, weil man sie nicht versteht. Geht was schief mit dem System wird man dann von naseweisen Linuxgurus gefragt, was das Syslog sagt. Der 0-8-15 User weiß nicht mal, dass es sowas gibt. Also ls -l /var/log/syslog eingeben:

> ls -l /var/log/syslog
-rw-r----- 1 syslog adm 71855 Feb 23 01:07 /var/log/syslog

Mit 70kb ein ganz schön fettes Ding.

Mit less /var/log/syslog (less is more) kann man sich den Inhalt ansehen. Wenn etwas schiefläuft, dann oft richtig, und die gleiche Nachricht taucht 100fach im Logfile auf. Mit einer Länge von 3 Zeilen a 150 Zeichen kommt man leicht auf 45.000 Zeichen. Die Nachrichten zu entziffern ist schon eine Wissenschaft für sich, aber wenn man regelmäßig reinschaut kann man ja einzelnen Nachrichten nach und nach auf den Grund gehen. Und man bemerkt vielleicht, wenn das Logfile plötzlich ganz anders ausschaut.

Früher hatte ich ewig, über unterschiedlichste Distributionen und Versionen hinweg Meldungen im Syslog, dass 3 Systemfonts nicht gefunden werden konnten. Im laufenden Betrieb hat sich aber nie ein Fehler geäußert. Einmal wollte ich sie loswerden und habe das Netz durchsucht, aber weder fand ich einen Ort, um die Fonts endlich runterzuladen, noch einen Trick die Meldungen loszuwerden.

Überflüssige Fehlermeldungen sind nämlich ein Problem: Sie erhöhen das Rauschen, den Heuhaufen, in dem man dann die Nadel nicht findet.

Ein anderer Unbill war eine fehlerhafte Druckerdatei, bei hoch gesetztem Loglevel des Druckerdaemons. Der hat dann gleich 100 Zeilen Fehlerprotokoll ins Log geschrieben, und das minutenweise. Das wurde rasch zu einem Dateigrößenproblem.

Jetzt gibt es auch den wunderbaren Daemon logrotate. Der rotiert das Logsystem, und zwar insofern, als die Logdatei von gestern zu xy.0.log umbenannt wird, die von gestern, die xy.0.log hieß wird xy.1.log genannt – sinnvollerweise in umgekehrter Reihenfolge, und so weiter, und die älteste wird gelöscht. Und was älter als gestern ist wird gezippt, und da diese Logdateien oft hochgradig redundant sind, sind die gezippten Dateien oft wesentlich kleiner, als die frischen, ungezippten. Weil sysadmins so oft in diese Dateien schauen müssen, gibt es extra das Programm zless, dass ein less auf gezippte Texte ausführt.

Wir beenden den Exkurs zu den Logdateien und kommen zurück zum Thema. Als auf Stackexchange jemand fragte, wie ein grafisches Programm zeitgesteuert startet – er wollte etwas ähnliches wie Logdateien ansehen, dachte ich nach, wie ich das lösen würde, aber konnte ihm nicht konkret helfen, weil er eine Lösung für MacOS sucht. Aber so kam ich auf die Idee, 1x täglich könnte ich mir die Syslogdatei vorlegen, und wollte sehen, ob sich das nicht mit Orage lösen lässt, wo ich bemerkt hatte, dass man zur Benachrichtigung ein Programm starten kann.

Dieses Programm kann man leicht selbst schreiben, und von Orage starten lassen. Die Idee ist dabei, die oft ellenlange Ausgabe der Logdatei zu kürzen, so dass ähnliche Meldungen nur noch einmal auftauchen. Meine Logdatei zeigt etwa sowas an:

Feb 22 07:35:02 tux201t colord[1154]: (colord:1154): Cd-WARNING **: failed to get session [pid 9723]: Kein passendes Gerät bzw. keine passende Adresse gefunden
Feb 22 07:35:02 tux201t colord[1154]: message repeated 5 times: [ (colord:1154): Cd-WARNING **: failed to get session [pid 9723]: Kein passendes Gerät bzw. keine passende Adresse gefunden]
Feb 22 07:35:10 tux201t anacron[9507]: Job `cron.daily' terminated
Feb 22 07:35:10 tux201t anacron[9507]: Normal exit (1 job run)
Feb 22 07:39:33 tux201t kernel: [1253876.380868] sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
Feb 22 07:39:33 tux201t kernel: [1253876.380875] sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
Feb 22 07:39:33 tux201t kernel: [1253876.380877] sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
Feb 22 07:39:33 tux201t kernel: [1253876.380882] sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
Feb 22 07:49:01 tux201t CRON[10242]: (stefan) CMD (date >> $HOME/foo.dat)
Feb 22 07:49:33 tux201t kernel: [1254476.385144] sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
Feb 22 07:49:33 tux201t kernel: [1254476.385154] sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
Feb 22 07:49:33 tux201t kernel: [1254476.385160] sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
Feb 22 07:49:33 tux201t kernel: [1254476.385167] sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
Feb 22 07:59:33 tux201t kernel: [1255076.377070] sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
Feb 22 07:59:33 tux201t kernel: [1255076.377081] sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
Feb 22 07:59:33 tux201t kernel: [1255076.377086] sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
Feb 22 07:59:33 tux201t kernel: [1255076.377093] sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
Feb 22 08:00:01 tux201t CRON[10538]: (stefan) CMD (/home/stefan/bin/blogcounter.sh -w >> /home/stefan/.bloglog)
Feb 22 08:09:33 tux201t kernel: [1255676.380279] sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
Feb 22 08:09:33 tux201t kernel: [1255676.380286] sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
Feb 22 08:09:33 tux201t kernel: [1255676.380289] sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
Feb 22 08:09:33 tux201t kernel: [1255676.380293] sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
Feb 22 08:17:01 tux201t CRON[11053]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
Feb 22 08:17:01 tux201t cron[926]: Please install an MTA on this system if you want to use sendmail!
Feb 22 08:17:01 tux201t CRON[11052]: (root) MAIL (mailed 107 bytes of output but got status 0x00ff from MTA#012)

Bis auf die Uhrzeit wiederholt sich vieles, und bis auf die magischen Zahlen in Backsteinklammern.

Das kann man mit sed, dem StreamEDitor, rausfiltern. Außerdem brauche ich die Angabe ‚tux21t‘, meinen Rechnernamen nicht – da ist nur der eine.

​​​​​​​sed -r 's/.* tux201t//;s/kernel: .[0-9.]+. /kernel: /;s/CRON.[0-9]+./CRON/' /var/log/syslog

colord[1154]: (colord:1154): Cd-WARNING **: failed to get session [pid 9723]: Kein passendes Gerät bzw. keine passende Adresse gefunden
colord[1154]: message repeated 5 times: [ (colord:1154): Cd-WARNING **: failed to get session [pid 9723]: Kein passendes Gerät bzw. keine passende Adresse gefunden]
anacron[9507]: Job `cron.daily' terminated
anacron[9507]: Normal exit (1 job run)
kernel: sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
kernel: sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
kernel: sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
kernel: sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
CRON: (stefan) CMD (date >> $HOME/foo.dat)
kernel: sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
kernel: sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
kernel: sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
kernel: sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00

Das ist kürzer, und jetzt sind viele Zeilen identisch. Mit | sort | uniq -c | sort -r -n kann man die Ausgabe sortieren, mit uniq die wiederholten Zeilen löschen, uniq -c zählt dabei die gelöschten Duplikate, ein weiteres sort -r -n sortiert dann numerisch und reverse, das heißt hier absteigend.

110 kernel: sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
110 kernel: sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
110 kernel: sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
109 kernel: sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
18 CRON: (stefan) CMD (/home/stefan/bin/blogcounter.sh -w >> /home/stefan/.bloglog)
18 CRON: (stefan) CMD (date >> $HOME/foo.dat)
18 CRON: (root) MAIL (mailed 107 bytes of output but got status 0x00ff from MTA#012)
18 CRON: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
18 cron[926]: Please install an MTA on this system if you want to use sendmail!
8 dbus[986]: [system] Activating via systemd: service name='org.bluez' unit='dbus-org.bluez.service'
7 org.freedesktop.Notifications[1801]: /home/stefan/.cache/xfce4-notifyd-theme.rc:1: error: scanner: unterminated string constant

Jetzt wollen wir noch die Ausgabe an ein simples Grafikprogramm weitergeben. Hier bietet sich Zenity an, welches bei Xubuntu dabei ist – eine Alternative wäre xdialog – das wir mit der Größe 1400×600 starten, und für das wir ein paar Label festlegen.

​​​​​zenity --list --text="Syslog messages" --column="logmsg" --width=1400 --height=600

Zenity war hier schon Thema und soll nicht näher besprochen werden. man zenity oder zenity --help verraten das wichtigste in Kürze. Auch im Ubuntuusers.de führt in den Umgang ein.

Komplett sieht unser Programm also jetzt so aus:

#!/bin/bash
#

condense syslog ((c) GPLv3)

#
sed -r 's/.* tux201t//;s/kernel: .[0-9.]+. /kernel: /;s/CRON.[0-9]+./CRON/' /var/log/syslog \
| egrep -v "Starting Hostname Service.|Started Hostname Service" | sort | uniq -c | sort -nr | \
zenity --list --text="Syslog messages" --column="logmsg" --width=1400 --height=600

Aufmerksame Leser haben bemerkt, dass sich hier noch ein Kommando eingeschlichen, hat, und zwar egrep -v "A|B" . Mit egrep -v kann man unerwünschte Zeilen ausfiltern, die ein Schlüsselwort enthalten. Diese zwei, durch ein Pipesymbol getrennte Namen A|B sind als A oder B zu lesen, und sind nach Bedarf zu erweitern, A|B|C|D … – so kann man Meldungen, die nur Erfolg verkünden, ausblenden. Wir wollen ja die unangenehmen Heinis identifizieren. Mit der Zeit wächst das sicherlich an, wenn man diszipliniert nach und nach allen Meldungen auf den Grund geht.

Weil die Befehlskette so lang ist, habe ich sie umgebrochen. Dazu benutzt man den Backslash, dem sofort ein Zeilenumbruch folgen muss, dann in der nächsten Zeile fortgesetzt.

Ich nenne sie syslog-view.sh, speichere sie in meinem bin-Dir ~/bin, welches im Pfad ist, und markiere sie mit chmod a+x ~/bin/syslog-view.sh als ausführbar.

Mit syslog-view.sh kann man sie jetzt aufrufen und sollte das auch testen. Bei Fehlern testet man sinnvollerweise erst die Filterung mit sed, dann die sort-Kette in Verbindung, schließlich ob man Zenity mit einer anderen Eingabe so aufrufen kann, und dann die Kombination.

Jetzt kommen wir zum eigentlichen Punkt, den Aufruf durch Orage. Hier sind jetzt die GUI-Freunde in ihrem Element. Wir klicken einen einzelnen Tag an, und kommen zum Tagesfenster. Da wählen wir Ereignis oder Aufgabe – der Unterschied hat sich mir noch nicht erschlossen, und dann, links unter Datei, das Symbol für Neu, das Blatt mit dem Plus.

orage-tagesfenster

Wenn wir schwach sind im Entscheiden, dann können wir hier wieder von Ereignis zu Aufgabe wechseln oder zurück. Ich war für Ereignis. Da vergeben wir einen Titel. Ort hat wenig Sinn, aber ich bin kein Orage-Crack, womöglich entgeht mir da was. Und eine Uhrzeit legen wir fest – 18:05 halte ich für eine excellente Entscheidung. Oft bin ich da schon wach.

orage-ereignis-neu1

Rubriken sind wohl interessant, wenn man viel mit Orage verwaltet. Priorität habe ich so gelassen und alles. Dauer 30 Minuten steht auch nur so da.

Nächster Reiter, Erinnerung, es wird spannend! orage-erinnerung1

Mit 0:0:0 als Erinnerungszeitpunkt verraten wir Orage, dass die Anwendung selbst die Aufgabe ist. Wenn wir ins Konzert wollen, und eine Stunde früher los müssen, dann würden wir da wohl 1 Stunde eintragen. Wir sind von der Sorte hier-und-jetzt. Anwendung wollen wir benutzen, und tragen den Pfad zum Programm und Programmnamen ein. Ob Shellkürzel wie $HOME oder ~/ funktionieren würden habe ich nicht getestet.

Nächster Reiter, Wiederholung:

orage-wiederholung1

Alle Stunde ist wohl etwas oft. Das hatte ich zum Testen eingestellt. Täglich, wöchentlich, monatlich und jährlich stehen noch zur Auswahl, und man könnte auch 2-wöchentlich oder sowas festlegen. Komplexität bitte selbst erforschen.

Tja, und jetzt poppt täglich mein Logmelder auf, und ich darf mich fragen, was der Colordämon wohl ist, und was er macht. Das Ziel ist es, nach und nach den Meldungen auf den Grund zu gehen, diejenigen zu beseitigen, die ich beseitigen kann, und diejenige auszufiltern, die harmlose Statusmeldungen sind. So dass das Logfile leerer wird, und neue Fehler dann auch auffallen.

Achso – wie sieht es in Zenity aus?

zenity-logview

Die Überschrift, man solle was auswählen, kommt vom Listenmodus zenitys. Womöglich kann man sie durch was eigenes ersetzen. Ob man OK oder Abbrechen drückt hat den gleichen Effekt – das Fenster schließt sich. Man könnte bei OK die Ausgabe auffangen und damit was anstellen (automatisierte Googlesuche, etwa, oder Frage eröffnen bei Ubuntuusers.de, oder Email an den persönlichen Linuxguru schicken.)

Ich hatte mal einen Nullmailer installiert; das wozu ist eine andere Geschichte, die hier nicht erzählt werden soll. Dann klappte es nicht mehr, wurde aber auch nicht mehr gebraucht. Daher jedenfalls stammt dieser Eintrag mit 18 Meldungen, ich solle einen MTA (Mail transport agent) installieren. Zenity kann man, meine ich, mitteilen, ob man die Zeilen edieren darf. Ja, das werde ich noch einstellen, wenn Hinweise in den Kommentaren nicht schneller sind, denn so, wie es jetzt ist, kann man schlecht den Text kopieren, um ihn selbst ins Google-Suchfeld einzugeben.

 

Advertisements

 – WordPress Ministatistik, DIY – 

wp-mini-statistik

Vor 2-3 Tagen hat WordPress die Ministatistik, wie ich sie in etwa oben nachgemalt habe – einen Screenshot habe ich nicht – aus der Ansicht geworfen. Wer selbst keinen Blog hat, kennt das gar nicht – auch ich bekomme die nur auf meinem eigenen Blog angezeigt, nicht auf dem anderer Leute. Das war ein Minibalkendiagramm, das stündlich aktualisiert wurde, wenn man die Seite neu lud, und die letzten 48 h umfasste, erinnerte, je nach Besucherzahlen, manchmal an das Ciscologo, welches seinerseits auch an eine Hängebrücke erinnert.

Wer einen Premiumaccount hat, kann da vielleicht auch eigene Widgets platzieren. In dem von mir verwendeten 0-8-15-Layout im Free-Tarif war das allerdings keine Option die man aus-, abwählen oder platzieren konnte.

Ich habe es gleich schmerzlich vermisst. Bei den Einstellungsoptionen fand ich keinen passenden Ersatz. Unter Design/Widgets/Blogstatistik fand ich lediglich einen Zähler aller Besucher, der, wenn man die Überschrift und die Einheiten löscht, so aussieht:

zaehler

Den sehen jetzt alle, was mich nicht stört, außer der Platzverbrauch, aber man sieht natürlich nicht mehr wie viele pro Stunde da waren und muss die Zahl vom letzten Mal im Kopf haben, um daraus den jüngsten Verkehr abzuleiten. Nichts, womit ich mich belasten will, aber eine Basis um selbst was zu bauen.

Wer sein eigenes WordPressblog selbst hostet hat andere Möglichkeiten, aber da ich mich nicht um die Internas des Blogs kümmern will, absichern, Backups und das alles, muss ich mir anders behelfen.

Eine Webseite kann man auch programmgesteuert abrufen. Gut – das machen ja auch Firefox, Chromium, Safari und Opera, aber diese stellen sie auch grafisch dar. Man kann einfach den HTML-Code runterladen, und in diesem sieht der Zähler so aus (Zeilenumbrüche und Einrückung im Original anders):

<div id=“secondary“ class=“widget-area“ role=“complementary“>
<aside id=“blog-stats-4″ class=“widget widget_blog-stats“>

<h3 class=“widget-title“></h3>
<ul>
<li>184,914 </li>
</ul>
</aside>

Anhand der Zahl ist der Block leicht zu finden. Den Quellcode kann man sich auch im Browser ansehen, aber man will ja nicht stündlich die eigene Webseite manuell speichern, also das erledigt man mit wget:

wget https://demystifikation.wordpress.com/

für andere Webseiten eben mit einer anderen Adresse. Weil ich den Widget-Titel im Design gelöscht habe ist das leer bei mir. Gespeichert wird das runtergeladene unter index.html. Allerdings brauche ich gar nicht die ganze Datei sondern will da nur einen Teil aausfiltern, deswegen sage ich mit -O wo der Output hinsoll, und mit einem verlorenen Minuszeichen, dass es auf die Konsole ausgegeben werden soll.

wget -q https://demystifikation.wordpress.com/ -O -

Das -q steht für quiet und unterdrückt irgendwelche Statusmeldungen von wget, wieviel Prozent der Arbeit schon geleistet ist, und solchen Firlefanz.

Den Output filtere ich dann mit grep auf die Zeile, die den HTML-Code ‚<aside id=“blog-stats-4‘ enthält, wobei -A1 bewirkt, dass eine zusätzliche Zeile ausgegeben wird, und als zweiten Filter nutze ich sed, dem ich sage, dass ich vom Listitem nur die Folge an Ziffern und Kommazeichen will, und das Kommazeichen soll dann auch weg.

sed -nr "s/.*<li>([0-9,]+).<\/li>.*/\1/;s/,//p"

Wer oft HTML, XHTML und XML-Code parsen muss wird vielleicht lieber zu einem Tool wie xmlstarlet greifen, welches den Vorteil hat, robust gegenüber Zeilenumbrüchen zu sein oder dem Vorkommen von Suchbegriffen in Kommentaren, aber das ist hier nicht zu erwarten. Sollte sich das HTML ändern, dann womöglich auch gleich soviel, dass einem das auchnicht weiterhilft.

Im ganzen sieht die Kette dann so aus:

counter=$(wget -q https://demystifikation.wordpress.com/ -O - | grep -A1 '<aside id="blog-stats-4' | sed -nr "s/.*<li>([0-9,]+).<\/li>.*/\1/;s/,//p")

Jetzt steht in der Variablen counter nur noch die Zahl 184914 und gespeichert wurde gar nichts.

lastcount=$(< ~/.blogcounter)
increase=$((counter-lastcount))
#
old=$(date -r ~/.blogcounter +%s)
now=$(date +%s) 
timespan=$((now-old))
#
heat=$(test $timespan -ge 0 && echo $((increase*3600/timespan)) || echo "--")

Dann sage ich

  • lastcount soll der Inhalt der Datei ~/.blogcounter sein, eine versteckte Datei, die das Programm später selbst schreiben wird, so dass es beim ersten Mal einen Fehler meldet, weil die Datei nicht vorhanden ist.
  • increase ist einfach die Differenz von altem Counter und Istzustand
  • old ist der Zeitstempel der Datei Blogcounter in Sekunden seit dem 1.1.1970
  • timespan ist die Zeitdifferenz zu now, also jetzt

 

heat=$(test $timespan -gt 0 && echo $((increase*3600/timespan)) || echo "--")

Heat sollen die mittleren Besucher pro Stunde sein seit der letzten Protokollierung, also wenn nach 30 Minuten 10 gezählt wurden 20 und wenn die Messung ausgefallen ist (Rechner aus) eventuell 5, wenn es nach 2 h 10 waren.

Getestet wird, ob die Zeitspanne > (greater than) 0 ist, dann sei heat der Wert der Berechnung, sonst „–“ (Division durch Null vermeiden!).

Jetzt wird es ein wenig kompliziert – wieso?

Nun, einmal will ich das Programm nutzen, um nur die stündlichen Differenzen zu protokollieren. Andererseits will ich jederzeit abfragen können ohne etwas zu protokollieren, etwa weil ein Beitrag von einem Alphablogger verlinkt wird, und plötzlich 1000e Besuche bekommt, so dass ich im 10-Minutentakt nachsehe, was das Volk macht.

test 1$# -gt 10 && test $1 = "-w" && echo $counter > ~/.blogcounter \
|| echo -e "Anzahl Anstieg /h Intervall (min) Messpunkt\n-------------------------------------------------------"

Das test 1$# ist ein furchtbarer Hack. $# ermittelt, wieviele Argumente einem Skript übergeben wurden. Aus unerfindlichen Gründen ist das aber nicht 0, wenn es keine Argumente sind, sondern nix, leer, nada, Nil, void, „“. Und dann scheitert der Test. Also klebe ich eine 1 davor und tesst nicht auf größer als 0, sondern auf größer als 10. Eigentlich müsste es da was eleganteres geben.

Waren es mehr als 0 Argumente prüfe ich, ob der Inhalt des 1. Arguments „-w“ war (w wie write, schreiben). Mit mehr oder anderen Argumenten rechne ich übrigens nicht.

War auch dies prima, dann, und nur dann schreibe ich die aktuelle Zahl in die versteckte Datei, die oben bereits erwähnt wurde. Ansonsten gebe ich eine Überschrift aus.

echo -e "$counter $increase $heat $((timespan/60)) $(date '+%H:%M %F')"

So oder so gebe ich dann die Werte aus, Zählerstand, Differenz, Seitenaufrufe /h seit letzter Messung und das Datum. So sieht ein isolierter Scriptaufruf (blogcounter.sh) aus:

Anzahl Anstieg /h Intervall (min) Messpunkt
-------------------------------------------------------
185203 0        0        22       20:22 2017-01-08

Etwas müde, gerade?

Seit 20 Uhr 0 Besucher, das sind 0 pro Stunde, Messintervall sind 22 Minuten und gemessen heute um 20:22 Uhr.

Außerdem hat Linux ja einen cron-Daemon, der chronologisch Dienste verrichten kann, wenn man im sagt wann und was. Den stellt man so ein:

daemonen

hilfreiche Linuxdaemonen, im Hintergrund wirkend

 0 * * * * /home/stefan/bin/blogcounter.sh -w >> /home/stefan/.bloglog

Das heißt jeweils zur Minute 0, jede Stunde (*), jeden Tag der Woche, des Monats usw. soll das Skript oben, das bei mir unter /home/stefan/bin/blogcounter.sh liegt ausgeführt werden, und die Ausgabe an die Datei /home/stefan/.bloglog angehängt werden (die erstellt wird, wenn sie noch nicht existiert). Das -w unterdrückt die Ausgabe der Überschrift, die man nicht für jede Zeile im Log haben will, und sorgt dafür, dass der Wert auch in die Datei ~/.blogcounter geschrieben wird.

Und dann gibt es noch ein kleines Script bloglog.sh, das so aussieht:

#!/bin/bash
#
# Blogtrafficlog der letzten 48 Stunden ausgeben
#
echo -e "Anzahl Anstieg Heat(/h) Intervall (min) Messpunkt"
echo "-------------------------------------------------------"
tail -n 48 ~/.bloglog | tac

Tail gibt nur die letzten 48 Zeilen der Datei ~/.bloglog aus, tac ist das Gegenteil von cat und gibt die Zeilen in umgekehrter Reihenfolge aus, also die jüngsten zuerst. Je nach Bildschirm und Fontgröße empfiehlt es siich, die Zahl an die eigenen Bedürfnisse anzupassen.

Die Ausgabe von bloglog.sh sieht beispielsweise so aus:

Anzahl Anstieg Heat(/h) Intervall (min) Messpunkt
-------------------------------------------------------
185205  1  1 60 22:00 2017-01-08
185204  1  1 60 21:00 2017-01-08
185203 22 21 60 20:00 2017-01-08
185181  0  0 59 19:00 2017-01-08
185181  4  4 60 18:00 2017-01-08
185177 10 10 60 17:00 2017-01-08
185167  3  2 60 16:00 2017-01-08
185164  7  7 59 15:00 2017-01-08
185157  4  4 60 14:00 2017-01-08
185153  3  3 60 13:00 2017-01-08
185150 185150 187177 59 12:00 2017-01-08
 -185118 -183134 60 11:00 2017-01-08
185118 16 16 60 10:00 2017-01-08
185102  5  4 60 09:00 2017-01-08
185097  0  0 59 08:00 2017-01-08
185097  0  0 60 07:00 2017-01-08
...

Das genaue Layout kann mit WordPressmitteln nicht ohne übermäßigen Aufwand getreu wiedergegeben werden – ich denke so geht es.

Die zwei Zeilen, die hervortreten deuten darauf hin, dass der Counter um 11:00 nicht lesbar war, auf Null gesetzt wurde, so dass die Zahl einbrach um dann hochzuschnellen – ein Grund dafür ist mir nicht erkenntlich, aber es zeigt, dass das Skript insofern robust ist, als es 2 Stunden später wieder brav seinen Job tut.

Pro Stunde fallen ca. 25 Bytes Daten an, das macht 600 am Tag, rd. 220.000 im Jahr und in 100 Jahren 22 MB – dürfte also, selbst wenn es vergessen wird und ständig, über viele Systemaktualisierungen weiterläuft, nie Probleme verursachen.

Hier nochmal das ganze  blogcounter.sh-Skript am Stück:

#!/bin/bash 
#
# Blogcounter ermitteln
# Zahl erfassen
# Differenz zur letzten Messung berechnen
# Differenz ausgeben
# Zahl speichern
# Zeit der letzten Messung erfassen
# Anstieg ermitteln
# Hits pro Stunde ermitteln
#
counter=$(wget -q https://demystifikation.wordpress.com/ -O - | grep -A1 '<aside id="blog-stats-4' | sed -nr "s/.*<li>([0-9,]+).<\/li>.*/\1/;s/,//p")
lastcount=$(< ~/.blogcounter)
increase=$((counter-lastcount))
#
old=$(date -r ~/.blogcounter +%s)
now=$(date +%s) 
timespan=$((now-old))
#
heat=$(test $timespan -gt 0 && echo $((increase*3600/timespan)) || echo "--")
# only write to counter file if param -w was given
# allows for hourly logged values, triggered by cron (with -w) and
# intermediate views without logging 
test 1$# -gt 10 && test $1 = "-w" && echo $counter > ~/.blogcounter || echo -e "Anzahl Anstieg /h Intervall (min) Messpunkt\n-------------------------------------------------------"
#
# Ergebnisse loggen. Das ganze sollte per cron stündlich laufen. Mit e. Script
# die letzten 24 oder 48 Messungen anchauen.
#
# Crontabzeile: 
# 0 * * * * /home/stefan/bin/blogcounter.sh -w >> /home/stefan/.bloglog
#
echo -e "$counter $increase $heat $((timespan/60)) $(date '+%H:%M %F')"

Weiterführende Hilfe bekommt man zu den einzelnen Befehlen mit

  • man wget
  • man sed
  • man tail
  • man date
  • man bash
  • help test
  • man tac
  • man cron
  • man crontab

und zu allen Befehlen, außer test, (was ein Kommando der Bash ist) auch mit PROGRAMM –help.

Vor einiger Zeit habe ich ein kleines Skript, journal.sh, vorgestellt, um Messwerte automatisch zu datieren und mit einem Stichwort in einer Datei abzulegen.

Angeregt durch Erzählmirnix, die auch den Blog Fettlogik überwinden betreibt, wollte ich meine Werte auch in grafischer Form aufbereitet sehen, aber nicht mit einer schnuckeligen App, einerseits weil ich gar kein Smartphone warte, andererseits will ich mein Gewicht auch nicht in der Cloud speichern und nach jwd leaken. Solche Apps scheinen oft mitteilungsfreudiger zu sein, als dem Anwender lieb ist.

gewicht

Bevor ich aber zum HowTo komme noch ein Abstecher zu einer anderen Nützlichkeit. Die Shell kennt Funktionen, und solche Funktionen kann man in der Datei ~/.bashrc ablegen. Dann stehen sie in jedem neu geöffneten Shellfenster zur Verfügung. Da ich mein Journal für immer wieder die gleichen Stichworte nutze (kg, ezig, rad) habe ich mir Funktionen geschrieben, die prüfen, ob ich neben dem Stichwort weitere Eingaben übergebe – wenn nicht wird mir nur die Liste bisheriger Werte ausgegeben. Ansonsten wird zuerst der neue Wert eingegeben. Und statt journal.sh 82,7 kg einzugeben gebe ich nur kg 82,7 oder kg ein.

Das ist für faule Menschen sehr praktisch.

kg ()
{
test $# -ge 1 && journal.sh $1 „kg“;
grep “ kg“ ~/journal.txt
}

ezig ()
{
test -n $# && journal.sh „ezig“ $1;
grep „ezig“ ~/journal.txt
}

Für ezig sieht es etwas anders aus, da dort ein Eintrag typischerweise unformatierter ist, etwa ezig 19,80 2 Päckchen neue Coils oder ezig 9,99 1L Basisliquid.

test $# -ge 1 prüft, ob die Zahl der Argumente größer-gleich 1 ist (-ge: greater-equal).

test -n $# prüft, ob die Argumentliste leer ist.

Soweit der Exkurs. kg liefert mir also eine Liste von Gewichtsmessungen, und in eine Grafik verwandelt man sie mit gnuplot. Angezeigt werden kann sie mit display, aber jeder andere Bildbetracher tut es, der das Bildformat beherrscht, etwa eog, inkview usw.

kg | sed ’s/^.. //;s/ kg//;s/,/./;s/ /., /‘ > gewicht.lst
gnuplot gewicht.plt && display gewicht.png

kg liefert also eine Liste an Gewichtsmessungen mit Datum.

So 2016.08.14 75.7 kg
Do 2016.08.04 76,8 kg
Di 2016.07.19 77.8 kg
So 2016.07.03 78.8 kg
So 2016.06.19 79.6 kg
Fr 2016.06.17 80.8 kg

Mit Sed schneide ich vorne den Wochentag weg. Wie man sieht erfasse ich undiszipliniert die Werte mal im deutschen, kontinentalen Format mit Komma, dann wieder im computernahen mit Punkt. Das zweite löscht das “ kg“ weg. Diese Kommas wandelt das dritte Sed-Kommando in Punkte um. Als Feldtrenner erwartet Gnuplot ein Komma, das macht das vierte Kommando und die Ausgabe leite ich in eine Datei gewicht.lst um.

Sed war hier ja schon gelegentlich Thema. Es steht für Strream-EDitor und wird von mir vor allem für solche Serien Suche-und-Ersetze-Kommandos genutzt (substitute). Jedes Semikolon trennt einen Befehl vom nächsten, daher vier Befehle. s/vorher/nachher/; bedeutet also Substituiere vorher durch nachher. Diese Kommandos sind leichter zu schreiben als zu lesen.

Dann kommt gnuplot zum Zuge, ein wahnsinnig mächtiges Werkzeug um ohne Open-Office Grafiken zu erzeugen – im Sinne von mathematischen, wissenschaftlichen Grafiken. Hier das Programm gewicht.plt:

set title „Gewicht nach Zeit“
set xdata time
set style data lines
# set terminal dumb feed 120 45
# set terminal svg
# set output „gewicht.svg“
#
set term png
set output „gewicht.png“
#
set timefmt „%Y.%m.%d.“
set format x „%m\n“
set xlabel „Monat“
set ylabel „Gewicht“
# # set autoscale y
set xrange [„2016.01.01″:“2016.12.31“]
set yrange [60:100]
# set autoscale y
set datafile separator „,“
plot „./gewicht.lst“ using 1:2 t „diaet“ w lines

Viele Kommandos sind sicher selbsterklärend; set title, xlabel, ylab el, xrange, yrange– das versteht sich von selbst aber die Syntax muss man natürlich kennen.

Das auskommentierte autoscale malt was, das Minimum und Maximum als Grenze nimmt. Damit würde aber über die Zeit der Graph mal auf der Gewichts- und immer auf der Zeitachse verzerrt – ich hätte lieber gleichbleibende Proportionen und muss dann an Sylvester das Programm anpassen. Dass auf der X-Achse die Zeit aufgetragen wird muss gesondert gesagt werden: set xdata time, Befehle um eine SVG-Grafik zu machen habe ich auskommentiert. Ebenso die praktische Option eine Asciigrafik im Terminal selbst auszugeben set terminal dumb feed 120 45  – das wären 120 Spalten bei 45 Zeilen und sollte natürlich an das eigene Terminal angepasst sein.

Das ganze einzurichten dauert natürlich, insbesondere wenn man die Programme erst installieren und sich in die Befehle einfuchsen muss, aber hat man es einmal eingerichtet ist es wesentlich komfortabler, als erst OpenOffice zu öffnen und eine CSV-Datei zu importieren, da die Achsen zu beschriften und den Grafiktyp auszuwählen oder den Wertebereich anzupassen. Für jede Messung will man auch nicht OpenOffice öffnen – dafür ist ein Kommando kg 77.7 doch sehr viel komfortabler.

Wer sich wundert, dass es im Graphen nur abwärts geht: Ich messe zwar mehrmals täglich, aber wegen der Wasserschwankung im Körper gibt es ein ständiges Auf-und-Ab. Also protokolliere ich nur den jeweils neuesten Rekord nach unten. Sollte ich wieder schwer zulegen würde ich wohl auch wieder einen höheren Wert protokollieren, aber zur Zeit läuft die Gesundschrumpfung ganz gut.

Sicher könnte man die Grafik noch ausbauen mit Linien für die Schwellwerte des BMI bei Übergewicht für die eigene Körpergröße, Adipositas I und II sowie Untergewicht, aber so bin ich erstmal zufrieden.

Display ist übrigens als Programm im Grafikpaket Image-Magick enthalten.

gnu

Die vorgestellten Skripte dürfen natürlich frei benutzt und nach Lust und Laune verändert werden.

 – pdftotext – 

deschner-ruler

Seit einiger Zeit bin ich stolzer Besitzer der ersten 8 Bände der Kriminalgeschichte des Christentums von Karlheinz Deschner. Die Seitenzahl von über 8000 fand ich jedoch erdrückend und startete einst einen Versuch das PDF in Text umzuwandeln um es mir von Software dann vorlesen zu lassen.

Das Ergebnis war recht erbärmlich. Ich wollte zwar pro Tag etwa 15 Minuten davon zum Einschlafen hören, und wäre damit, wie ich jetzt berechnen konnte, nach weniger als einem halben Jahr durch gewesen, die monotone Computerstimme führt aber dazu, dass man bereits nach 2 Minuten einschläft oder nicht einschläft, aber nach 3 Minuten nicht mehr zuhört, was die Stimme erzählt.

Jetzt habe ich einen zweiten Anlauf genommen und mir ein paar Audioprogramme installiert, die ich vergleichen wollte, und beschlossen den Text bei den übelsten Vertonungen vorher zu präparieren.

Die einfachste Herangehensweise ist es mit dem Befehl

pdftotext deschner.pdf deschner.txt 

aus den ca. 50MB PDF ca. 10MB reinen Text zu machen, aber dieser wird dann auf jeder Seite von der Seitenzahl (343), der Kapitelüberschrift, der Bandangabe und von der Seite unten noch mal in Klein ‚Karlheinz Deschner: Kriminalgeschichte des Christentums‘ unterbrochen.

Erst probierte ich mit Sed, dem Streameditor, diese Textstellen zu erkennen und zu löschen, was auch weitgehend klappte, wenn auch nicht optimal. Dann beschäftigte ich mich bereits mit einigen Feinheiten, auf die ich später noch kommen will.

Mit ein wenig Handbuchlesen, ausprobieren und der Zuhilfenahme anderer Programme kann man im ersten Arbeitsgang nämlich schon ein sehr ansehnliches Basisexemplar erzeugen.

mit

xpdf -z 100 deschner.pdf

öffnete ich den ultraschlanken und daher schnellstartenden PDF-Viewer xpdf im Zoommodus 100%. Die 100% sind wichtig, denn vom Screenshot wollen wir die Anzahl Pixel ablesen. Ich schoss also einen Screenshot, nur von der dargestellten Seite – nicht dem umschließenden Programm. Den speicherte ich als deschner.png um ihn mit gimp, dem GNU-Imaage-manipulation-Programm zu öffnen. Dieses hat am Rand Lineale, so dass ich ablesen konnte, wo ich das Dokument beschneiden muss, um das Brimborium (gelbe Pfeile) von Anfang und Ende der Seite loszuwerden. Den abzuschneidenden Teil habe ich vergilbt eingefärbt.

Die kurzen vertikalen Striche sind 10 Pixel, die mittleren 20 Pixel voneinander entfernt. 60 von oben sollte also passen (blaue Pfeile). Unten wären es etwa 820. Allerdings gibt man nicht die untere Koordinate an, sondern die Höhe, also die Differenz zu den 60 von oben, das wären also 760.

Außerdem gilt es die umfangreichen, schlecht les- und hörbaren Quellenangaben zwischen den Kapiteln auszumerzen. Die Seitenzahlen könnte man aus dem Inhaltsverzeichnis nehmen, wenn es eins gäbe – da nicht muss man sich grob in 1000er-Schritten durchs Buch iterieren und dann suchen, wo genau Fußnoten und beginnen und Dank an hilfreiche Leute enden. Mit -f 23 gibt man an, from page 23, mit -l 883 last page 883.

-t für to wäre wohl zu naheliegend gewesen. -x und -y sind für den oberen, linken Punkt zuständig, wo das Ausschneiden beginnen soll – den X-Wert kann man nicht weglassen, nur weil man in X-Richtung nichts wegschneiden will, wie ich feststellen musste, und was wohl  bei meinen ersten Experimenten zum frustrierten Abbruch der Experimentierphase führte. -H steht für Height, -W für Width, auch beides nicht weglassbar im Sinne von ’nimm alles‘.

Weitere benutzte Optionen sind:

-raw : keep strings in content stream order

-nopgbrk : don’t insert page breaks between pages

Ich glaube ‚raw‘ braucht es jetzt gar nicht mehr, es  hat aber wohl auch nicht geschadet. So hier also die Kommandos gruppiert. Viel Arbeit, aber wir reden ja auch von über 8000 Seiten:

 

pdftotext -f 23 -l 883 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.1.txt
pdftotext -f 1099 -l 1840 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.2.txt
pdftotext -f 1984 -l 2946 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.3.txt
pdftotext -f 3102 -l 3890 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.4.txt
pdftotext -f 4042 -l 5032 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.5.txt
pdftotext -f 5147 -l 6050 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.6.txt
pdftotext -f 6161 -l 6977 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.7.txt
pdftotext -f 7065 -l 7799 -raw -nopgbrk -y 60 -x 0 -H 760 -W 560 deschner.pdf d.8.txt

Zu den Vorleseprogrammen benötigt es ein wenig Vorwissen: Diese zerlegen einen Text in Silben und versuchen die Stimme an Wortgrenzen und Satzzeichen zu sinnvollen Lauten bewegen, die vorhergehenden und nachfolgenden Silben berücksichtigend. Das ist über verschiedene Sprache ein ähnliches Problem, aber natürlich von Sprache zu Sprache verschieden.

Was die Programme nicht kennen, das ist die Aussprache ganzer Wörter. Alles wird synthetisch produziert und ist daher für verschiedene Probleme wie geschaffen.

Ausländische Wörter werden gar nicht erst erkannt, und alles so ausgesprochen wie die eingestellte Sprache nun mal ist, hier also Deutsch. Es gibt zum Glück nur wenige englische Phrasen. Häufiger aber Lateinische Namen. Überhaupt Namen! David klingt wie Dafid. In Atheisten wird das ei wie in Frühstücksei gesprochen. 1953 wird als tausend-neunhundert-dreiundfünfzig gesprochen. Kontexterkennung ist auch Glückssache. Häufig finden sich Zeitspannen wie Regentschaften oder Lebenszeiten (523-569) und da liest der Text stumpf die zwei Zahlen vor, zum Glück ohne Klammern. Eckige Klammern werden aber als ‚eckige Klamer 319‘ gelesen. Fußnoten (roter Pfeil) werden als Zahl vorgelesen. Häufig verwendet Deschner die 3-Punkt-Ellipse … (anderer roter Pfeil)- da macht die Stimme eine für mich zu lange Pause.

Die häufigsten Ärgernisse habe ich mit einem Sedscript auszumerzen oder verbessern versucht. Oft kommt auch nach einem Absatz ein Name in Klammern, eine Quelle. Die habe ich, soweit möglich, gelöscht, das heißt, wenn es nur ein Zeichenfolge war (Wagner), aber nicht, wenn es mehrere Token waren, weil es auch Nebengedanken in Klammern gibt, die ich nicht opfern wollte.

Kontext ist auch Glückssache. S. 47 wird nicht zu Seite 47, andere Abkürzungen werden aber teilweise erkannt und aufgelöst.

Hier mein unfertiges Script für die Details:

s/David/Dawied/
#«
# Fußnoten im Audiostrom nicht hilfreich ("bla fasel.49", ... foobar«69, bar foo 96.)
s/\.[0-9]+$/./
s/[^ 0-9][0-9]+\././
s/«[0-9]+$/«/
#
# (870–849) wird nicht als "870 bis 849" vorgelesen, sondern als "870 849"
s/([0-9]+)–([0-9]+)/\1 bis \2/
#
# unverständlich, "Vau Char":
s/v\. Chr\./vor Christus/g
s/n\. Chr\./nach Christus/g
#
# Störende Quellen (Maier) löschen, löscht aber auch hilfr. Anmerkungen "Berlin (Deutschland)"
s/\([A-Z][a-z]+\)//
#
# sog. heilige 
s/\Wsog. /sogenannte/
#
# (S. 247) löschen (vgl. S. 245) (S. 312 f) (S. 999 ff)
s/(vgl\. )?S\. [0-9]+ ?f?f?\)//
#
# Karl I. (Karl Ih statt Karl der Erste)
#
# 1955 wird als eintausendneunhundert55 vorgelesen
s/1([0-9])([0-9]{2})/1\1-hundert \2/g
#

Die erzeugten Dateien sind alle etwa 1MB groß. Das Vertonungsprogramm soll aber nur Schnipsel von bis zu ca. 35kb abspielen können. Also müssenn wir jede Datei in ca. 30 Teile zerlegen, oder sagen wir 40, um auf der  sicheren Seite zu sein.

Mit

for i in {1..8}; do sed -rf feinjust.sed -i d.$i.txt ; done

lassen wir die Sedbefehlskaskade auf die 8 Dateien los. -r steht für regexp, und erspart uns in der Steuerdatei die runden Klammern zu maskieren. -f liest die Sedbefehle aus der folgenden Datei (file), -i ändert diese an Ort und Stelle (in place), so dass wir die Ausgabe nicht in eine neue Datei lenken müssen.

Die Zeilenlänge ermitteln wir mit wc (word count) und splitten die Bücher in je 40/41 Teile auf, 41, weil die Division einen Rest lassen kann, der bei der Multiplikation dann beim Buch 40 zu kurz kommt (nur einmal geht es genau auf, da ist Datei d.3.41.txt nämlich d.3.41.txt dann leer:

#!/bin/bash
#
#
blist=($(wc -l d.?.txt))
echo ${blist[@]}
# 21683 d.1.txt 18436 d.2.txt 23760 d.3.txt 19148 d.4.txt 23549 d.5.txt 22436 d.6.txt 20239 d.7.txt 18204 d.8.txt 167455 insgesamt
for buch in {1..8}
do
 zeilen=${blist[$((2*buch-2))]}
 faktor=$((zeilen/40))
 echo "Zeilen: $zeilen Faktor: $faktor"
 for part in {1..41}
 do 
 sed -n "$(((part-1)*faktor+1)),$((part*faktor))"p d.$buch.txt > d.$buch.$part.txt
 done
done

Jetzt haben wir 8×41-1 Dateien. Wir prüfen noch, ob keine zu groß wurde:

find -name „d.?.*.txt“ -size +34k -ls

Nein, alles bestens. mit +29k kann man sehen, dass der Befehl funktioniert.

Fast sind wir soweit, dass wir was hören. :)

Mit einer Schleife gebe ich die Texte an das Vorlesescript weiter und gebe dabei die Uhrzeit, den Dateinamen und deren Inhalt aus. So kann man doch mitlesen und kontrollieren, wenn unverständliches kam. Man sieht, dass Die Dateien mitten im Satz zerschnitten sind – das ist bei ½-stündigen¹ Audiofiles verschmerzbar und mir zu viel Arbeit, es benutzerfreundlicher zu machen.

for i in {15..16}; do echo; ls d.1.$i.txt; date; cat d.1.$i.txt; textlesen.sh d.1.$i.txt; done; date

d.1.15.txt
Di 24. Nov 03:20:22 CET 2015
lecker. Sie sind voll von »Dünkel« und »prunkenden
Phrasen«, sind geil und lügen. Ihre Einrichtungen,
ihre Sitten, ihre Religion und Wissenschaft, alles ist
»albern«, »vielfältige Torheit«, »wahnwitzig«.

Fehlt noch das Vorlesescript textlesen.sh:

#!/bin/bash
pico2wave -l=de-DE -w=/tmp/${1}.wav "$(cat ${1})"
# aplay /tmp/${1}.wav # && rm /tmp/${1}.wav
vlc /tmp/${1}.wav # && rm /tmp/${1}.wav

pico2wave wandelt mit language=deutsch -writing-to /tmp/$1.wav um, was mit cat aus der übergebenen Datei gelesen wird.

Erst hörte ich es mit play an, aber bei vlc habe ich einen Knopf um die Ausgabe anzuhalten, kann zurückspringen usw.

Das Ergebnis ist noch immer hölzern, aber man kann es zur Not anhören. :) Vielleicht probiere ich noch weitere text-to-speech-Lösungen (tts) bzw. Sprachsynthesizer oder finde andere Verbesserungen.

Empfehlungen werden gerne entgegen genommen, bevorzugt natürlich freie Software für Linux.


¹ oben war von ¼-stündigen Teilen die Rede. Das erste Skript erzeugte auch solch kürze Dateien, weil ich grober geschätzt hatte mit der Zeilenzahl. Mit dem Wissen, dass die Dateien alle nur ca. 15kb groß werden habe ich jetzt die Zeilenzahl erhöht und so längere Stücke erhalten.

Ein Register für’s PDF

Kürzlich stand ich vor der Aufagabe ein Orts- und ein Personenregister für ein PDF zu erzeugen. Der Text lag druckfertig als PDF vor. Das Personen- und Ortsregister als Wörstdokument (natürlich!) – ließ sich aber problemlos als Text speichern, so dass jeweils ein Eintrag pro Zeile ausgegeben wurde – unter Umständen eben länger als eine Bildschirmzeile, weil nicht nur der Name dastand, sondern üppig anreichernde Informationen.

Mit Linuxmitteln ist das eine Aufgabe, die sich nicht vollautomatisch erledigen lässt (nicht dass ich wüßte), aber viele Arbeitsschritte lassen sich teilautomatisieren. Sehr zum Nachteil der armen Textverarbeiter kennen diese natürlich nur selten die Möglichkeiten kleiner Programme wie grep, sed, sort, cat, head, tail und all die anderen. Sonst könnten sie sich das Leben oft selbst vereinfachen. Weiterlesen

Auf den Adminseiten von WordPress gibt es ein paar Länderstatistiken, d.h. es wird aufgelistet aus welchem Land wieviele Besucher kamen – heute, gestern, 7 Tage, 1 Monat, 1 Jahr oder die gesamte Blogzeit betrachtend.

Das wird auf einer Karte schön dargestellt, wenn auch nicht ganz zu meiner Zufriedenheti.

Bild

Weiterlesen

Störenfried Grafikterminal

Vielleicht kennt Ihr das Spiel. Man schlägt mit verbundenen Augen ein Lexikon oder Wörterbuch auf, und piekst mit einer Nadel oder einer Bleistiftspitze auf ein Wort. Das wiederholt man und muss dann aus den zufällig gewählten Worten eine Geschichte bilden oder einen Satz. Das kann ein Partyspass sein oder ein Trick, die eigene Kreativität anzuregen.

Statt sich mühsam die Augen zu verbinden und beim Gestocher zwischen den Wörtern mühsam zu entscheiden, welchem Wort die Stiftspitze nun näher war ist ein handlicher Rechner mit Shellscript viel handlicher, vorzugsweise ein Linuxrechner mit lustigen Pinguinaufklebern, OSX soll angeblich auch gehen, notfalls sogar Ballmerware für die es Native Win32 ports of some GNU utilities gratis und quelloffen gibt, ein unschätzbares Sammelsurium nützlicher Programme, von  cat über grep zu sed und wc. Ich habe vor ab und zu das ein oder andere kurz vorzustellen, und zum Experimentieren anzuregen.

Hier unten sehen wir eine Unsitte von Programmierern, nämlich ein ganzes, kleines Programm in eine Zeile zu quetschen:

<cite>

dat=/usr/share/hunspell/de_DE.dic; wcl=$(wc -l $dat); for dummy in foo bar; do z=$((RANDOM*RANDOM%${wcl/ */})); sed -n ${z}p $dat; done

</cite>

Störenfried/EPSTm

Graphikterminal/Sm Weiterlesen