Archiv der Kategorie: Software

Alles was mit Software zu tun hat

dd-Backupfortschritt mit pv visualisieren

Vollsicherungen gesamter Festplatten oder Partitionen lassen sich mit dem Unix-Tool „dd“ schnell und einfach anfertigen. Während das Tool automatisiert wohl keine Wünsche offen lässt ist es ein wahrer Quählgeist, wenn man dringend auf die Fertigstellung eines Jobs wartet, denn eine automatische Ausgabe des Fortschirttes ist nicht vorgesehen. Zwar kann man sich hier behelfen, in dem man über den „kill„-Befehl das Signal „SIGUSR1“ an den Prozess sendet und so die Anzeige der verarbeiteten Datenmenge erzwingt, wirklich komfortabel ist dies jedoch nicht.

Senden von SIGUSR1

Bild: https://adlerweb.info/blog/wp-content/uploads/2014/11/pv1-300×98.png
Um das Signal SIGUSR1 an einen Prozess zu senden sollte im ersten Schritt dessen Prozess-ID (PID) ermittelt werden, hierzu kann man in der Ausgabe „ps“ nach dem zuvor gestarteten „dd„-Befehl suchen. Ich nutze zur Suche im Beispiel „grep„. Da zum Zeitpunkt des Schreenshots mehrere „dd„-Prozesse liefen suche ich zudem nach der Quelle des Testjobs (urandom).

kronos ~ # ps xa | grep "dd" | grep urandom
23204 pts/24   R+     0:24 dd if=/dev/urandom of=/dev/zero

Mit dieser ID kann man nun das Signal über den Befehl „kill“ absetzen. „dd“ verarbeitetet dieses Signal intern, das Programm wird hierdurch nicht beendet.

kronos ~ # kill -SIGUSR1 23204

Während auf der aktuellen Konsole keine Ausgabe erfolgt müsste dd nun einen Status ausgeben, welcher u.A. die verarbeitete Datenmenge sowie die Geschwindigkeit enthält:

162183+0 Datensätze ein
162182+0 Datensätze aus
83037184 Bytes (83 MB) kopiert, 37,7423 s, 2,2 MB/s

 

Wer sich einen übersichtlicheren und automatisierten Status wünscht kann hier mit dem Zusatztool „pv“ (Pipe Viewer) nachhelfen. Statt die Daten direkt von „dd“ an das Ziel schreiben zu lassen werden sie durch „pv“ geleitet, welches wiederum eine statistische Auswertung anzeigt. Als Ziel kann dann über einen weiteren „dd„-Prozess wieder eine Datei oder Gerät verwendet werden, alternativ gehen natürlich auch Kompressionstools wie „gzip“ oder man lässt die Daten z.B. mittels „nc“ (netcat) oder „SSH“ (Secure Shell) zur Speicherung an einen anderem Rechner senden.

Beispiele mit „pv

Bild: https://adlerweb.info/blog/wp-content/uploads/2014/11/pv2.png

Daten in Datei speichern

dd if=/dev/lvm/vm-102-disk-1 | pv -pterabs 32g | dd of=vm-102-disk-1.img
  15GiB 0:20:34 [  19MiB/s] [12,5MiB/s] [============================================>                                                      ] 46% ETA 0:23:12

Daten über gzip komprimieren und in Datei speichern

dd if=/dev/lvm/vm-102-disk-1 | pv -pterabs 32g | gzip > vm-102-disk-1.img.gz
  15GiB 0:20:34 [  19MiB/s] [12,5MiB/s] [============================================>                                                      ] 46% ETA 0:23:12

Daten über gzip komprimieren, per SSH mit schwacher Verschlüsselung an einen anderen Rechner senden und dort in Datei speichern

dd if=/dev/lvm/vm-102-disk-1 | pv -pterabs 32g | gzip | ssh -c arcfour,blowfish-cbc backup@cautio.lan.adlerweb.info 'dd of=/var/backup/vm-102-disk-1.img.gz'
Password:
 251MiB 0:00:23 [12,6MiB/s] [10,8MiB/s] [>                                                                                                  ]  0% ETA 0:49:38

 

Wichtig hierbei ist, dass „pv“ am Ende die Größe der Quelldatei/des Quellgerätes genannt wird, in diesem Fall 32 GB. Ingesamt bedeuten die Optionen folgendes:

-p Fortschrittsbalken anzeigen
-t Bisher vergangene Zeit anzeigen
-e ETA, also erwartete Restzeit, anzeigen
-r Aktuelle Datenrate, also „Geschwindigkeit“, anzeigen
-a Durchschnittliche Datenrate anzeigen
-b Bereits kopierte Datenmenge anzeigen
-s Größe der Quelle in Byte, k,m,g,… möglich

Alternative Reihenfolge zum besseren Merken: pertabs (per tabs) oder für Nutzer diverser Imageboards betraps.

Die Ausgabe ist wie folgt zu lesen:

  15GiB        0:20:34  [  19MiB/s] [12,5MiB/s] [======      ] 46% ETA 0:23:12
Kop.Datenmenge|Verg.Zeit|Datenrate|Ø Datenrate | Fortschritt      |Restzeit

Damit wäre der nervöse Admin mit beruhigenden Statistiken versorgt und weiß wie lange er sich noch gedulden muss – eine Ausrede weniger die Backups zu vernachlässigen. Natürlich kann „pv“ auch für andere Konstrukte verwendet werden, welche mit einer Pipe arbeiten.

MySQL/MariaDB unter Linux mit ZFS: Operating system error number 22 in a file operation

Nachdem LVM eine Qual ist wenn es um die Konfiguration von RAID geht (anm: Natives LVM-Raid, nicht md) und btrfs auf mehreren meiner Systeme gerne mal Dateien vergisst habt ich mich nach langer Zeit nochmal an ZFS gewagt. Die Funktionspalette ist beeindruckend: Integriertes RAID, integriertes Volumemanagement, Subvolumes, Kompression, Quota, etc. Alles natürlich verzahnt, sodass ein RAID-Rebuild wirklich nur belegte Dateisystembereiche rekonstruiert. Einzig die statische RAID-Konfiguration ist wenn man von LVM kommt etwas bedauerlich. Ansonsten scheint die Linux-Portierung des eigentlich von Solaris stammenden Systems inzwischen durchaus stabil.

Genug geredet, eigentliches Thema: MySQL unter ZFS. Als guter Einstieg sollte man hier einen Blick auf die Arch-Wiki werfen, welche einen Blick auf die Blockgrößen und Cache-Eigenheiten wirft. Doch egal wie: MySQL bzw. MariaDB haben noch eine Gemeinheit im Paket: Direct IO.

Da MySQL ein eigenes Caching implementiert versucht es über O_DIRECT die Dateicaches des Betriebssystems zu umgehen. Im Falle von ZFS ist dies durch den Aufbau nicht sonderlich hilfreich und wird durch den Linux-Treiber nicht unterstützt. Während die meisten Programme automatisch auf klassisches IO zurückfallen verabschiedet sich MySQL mit folgenden Log-Einträgen:

141019 18:07:42 InnoDB: Operating system error number 22 in a file operation.
InnoDB: Error number 22 means ‚Invalid argument‘.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
InnoDB: File name ./ib_logfile0
InnoDB: File operation call: ‚aio write‘.
InnoDB: Cannot continue operation.

Um das Problem zu beheben kann man die Datenbank über /etc/mysql/my.cnf in den klassischen IO-Modus zwingen, hierzu unter [mysqld] folgenden Eintrag ändern bzw. hinzufügen:

innodb_use_native_aio=0

im Anschluss sollte die Datenbank wieder wie gewohnt starten. Hinweis: Fehlender Direct-IO bringt auch Probleme mit KVM/LibVirt, auch hier sind ggf. Anpassungen notwendig.

[Gentoo] Installation von dev-ruby/ffi-1.9.4 schlägt fehl

Die Installation von dev-ruby/ffi-1.9.4, welches als Dep gezogen wurde, machte auf einem Server Probleme. Unter anderem war folgende Meldung zu lesen:

cannot load such file -- rspec/core/rake_task

Woher die Anforderung kam oder warum keine Dep da ist konnte ich nicht direkt sehen, ein manuelles Installieren von dev-ruby/rspec sollte jedoch die nötigen Voraussetzungen schaffen um das Kompilieren zu ermöglichen.

[Gentoo] Slot-Conflice durch Perl-Updates

Schon etwas älter, aber ab und zu stoße ich trotzdem drauf: Durch Perl kommt es bei Updates zu einem Slot-Conflice / Blocked Packages. Die Lösung wird z.T. gleich mitgeliefert:


* Remove all perl-core packages from your world file
* emerge --deselect --ask $(qlist -IC 'perl-core/*')
* Update all the installed Perl virtuals
* emerge -uD1a $(qlist -IC 'virtual/perl-*')
* Afterwards re-run perl-cleaner
perl-cleaner --reallyall

Arch Linux: Grafik-Software streikt nach Mesa-Update (10.2.7-2)

Seit vermutlich dem letzten Mesa-Update auf 10.2.7-2 vom letzten Wochenende ist offenbar OpenGL nicht mehr voll funktionsfähig – in meinem Fall verabschiedete sich Hugin mit der folgenden Meldung:

/usr/share/hugin/data/plugins/crop_cp.py
   CAT:Control Points
   NAM:Crop Control Points
/usr/share/hugin/data/plugins/woa.py
   CAT:Control Points
   NAM:Warped Overlap Analysis
/usr/share/hugin/data/plugins/top_five.py
   CAT:Control Points
   NAM:keep 5 CPs per image pair
/usr/share/hugin/data/plugins/shooting_pattern.py
   CAT:initial distribution
   NAM:6-1-1 Shooting Pattern
LLVM ERROR: Cannot select: intrinsic %llvm.x86.sse41.pblendvb
Speicherzugriffsfehler (Speicherabzug geschrieben)

Der Fehler ist schon im Arch-Bugtracker zu finden. Eine aktualisierte Mesa-Version (10.2.7-3) findet sich in Testing, hiermit tritt der Fehler nicht mehr auf.

Edit: Laut Website soll 10.2.7-3 wohl seit gestern in extra sein, auf meinem Mirror war dies jedoch noch nicht der Fall.

PEBCAK: Negative Temperaturen gibt’s ja auch…

In der BitNotice #44 hatte ich „mal schnell“ ein Script gebaut um die Werte eines DS18B20 Temperatursensors über einen Raspberry Pi in Volkszähler zu schaufeln. Was irgendwie nicht so ganz aufgefallen ist: Das Script konnte nur Plusgrade. Jetzt steht auf Github eine überarbeitete Version mit „-“ und etwas mehr Fehlerbehandlung. Danke an Peter, dessen Kühltruhe den Fehler aufgedeckt hat.

CAcert mit Chrome/Chromium unter Linux

CAcert ist an sich ja eine tolle Sache: Kostenfreie SSL-Zertifikate ermöglichen es auch kleinen Projekten Verschlüsselung zu nutzen ohne mit selbstsignierten Gerümpel anzufangen. Leider ist diese Zertifizierungsstelle nur bei wenigen Browsern vorinstalliert.

Unter Windows mit IE oder auf nahezu allen PC-Systemen per Firefox ist die Installation üblicherweise mit einem einfachen Klick auf der Webseite der CA erledigt – Chrome/Chromium unter Linux nutzen jedoch offenbar eine eigene Zertifikatsdatenbank.

Da die Warnungen und das manuelle prüfen auf Dauer natürlich nervig sind verweise ich mal einfach auf den offiziellen Installationsguide – hier ergänzt um einen kurzen Identitätscheck (Stand August 2014, gültig bis März 2033).

 

cd /tmp

wget -O cacert-root.crt "http://www.cacert.org/certs/root.crt"
wget -O cacert-class3.crt "http://www.cacert.org/certs/class3.crt"

openssl x509 -in cacert-root.crt -fingerprint -sha1 -noout
#Hier muss 13:5C:EC:36:F4:9C:B8:E9:3B:1A:B2:70:CD:80:88:46:76:CE:8F:33 erscheinen
openssl x509 -in cacert-class3.crt -fingerprint -sha1 -noout
#Hier muss AD:7C:3F:64:FC:44:39:FE:F4:E9:0B:E8:F4:7C:6C:FA:8A:AD:FD:CE erscheinen

certutil -d sql:$HOME/.pki/nssdb -A -t TC -n "CAcert.org" -i cacert-root.crt 
certutil -d sql:$HOME/.pki/nssdb -A -t TC -n "CAcert.org Class 3" -i cacert-class3.crt

Nach der Installation erkennt Chrome/Chromium die neue CA sofort, ein Neustart von System oder Browser ist nicht notwendig.

Poor mans PC-Interface – Multimeter per Webcam auslesen

Improvisieren? Kann ich. Derzeit teste ich mit einem Gerät herum, welches sich in regelmäßigen Abständen einschaltet – interessant für mich wäre es nun diese Zyklen genauer zu kennen. Zwar habe ich einige Energiekostenmessgeräte, damit lässt sich jedoch nur Min/Max bzw. der Durchschnitt errechnen, nicht jedoch wie oft das Gerät nun tatsächlich läuft. Hier würde ein Multimeter mit PC-Anbindung helfen, leider käme hierzu nur mein UniT in Frage, welches im Dauerbetrieb jedoch recht schnell mit leerer Batterie seinen Dienst einstellen würde. Meine „großen“ HPs besitzen zwar eine GPIB-Schnittstelle, den passenden PC-Adapter habe ich allerdings noch nicht fertig.

Bleibt nur ein anderer Ansatz: Optische Erkennung. Als Multimeter hält mein Rohde&Schwarz/Keithley her – durch die LEDs ist dessen Anzeige am einfachsten lesbar. Direkt davor sitzt nun eine Webcam, welche die Anzeige im Auge behält. Über die Software „motion“ stellt mein Linux-Server einen MJPEG-Stream bereit – ich bin diesen Weg gegangen, da ein ständiges Reinitialisieren der Kamera für einzelne Screenshots gerne zu Hängern führt.

Bild: https://adlerweb.info/blog/wp-content/uploads/2014/08/cam1.jpg

Ein kleiner PHP-Daemon fragt nun regelmäßig das letzte Bild ab, hierzu wird ein (modifizierter) Code des motion-Projektes verwendet:

$camurl='http://127.0.0.1:8081/';
$boundary="\n--";

$f = fopen($camurl,"r") ;

   if(!$f)
   {
        //**** cannot open
        echo "error";
   }
    else
   {
        //**** URL OK
         $r='';
         unset($p);
         while (substr_count($r,"Content-Length") != 2) $r.=fread($f,512);

         $start = strpos($r,chr(0xFF));
         $end   = strpos($r,$boundary,$start)-1;
         $frame = substr("$r",$start,$end - $start);

         //In $frame sind nun die rohen JPEG-Daten - diese können ausgegeben werden, gespeichert werden oder per imagecreatefromstring (gd) in PHP weiter verarbeitet werden
   }

Weiterhin wird das Bild passend beschnitten, gedreht und in ein invertiertes Schwarz-Weiß-Bild umgewandelt:

$src = imagecreatefromstring($frame);
$dst = imagecreatetruecolor(173,75);

imagecopy($dst, $src, 0, 0, 225, 66, 173, 75);
$dst = imagerotate($dst, 10, 0);
imagefilter($dst, IMG_FILTER_NEGATE);
imagefilter($dst, IMG_FILTER_GRAYSCALE);
imagefilter($dst, IMG_FILTER_CONTRAST, -100);

Im Anschluss wird über eine Reihe von „imagecolorat“-Abfragen für jede der 7-Segment-Stellen ein Array generiert – jedes Segment ist entweder an (1) oder aus (0). Zur besseren Erkennung wird jedes Segment an mehreren Stellen abgefragt und der Durchschnitt mit einem Schwellwert bewertet, so ist das System unempfindlicher gegen Rauschen.

Bild: https://adlerweb.info/blog/wp-content/uploads/2014/08/7SEG-208×300.png
(Im Array ist der Index entsprechend 0-6, nicht 1-7)

Am Ende steht ein Mapping, welches die erkannte Anzeige in einen Integer umwandelt

function seven2int($p) {
    $map[1][1][1][0][1][1][1] = 0;
    $map[0][1][0][0][1][0][0] = 1;
    $map[0][0][1][0][0][1][0] = 1;
    $map[1][0][1][1][1][0][1] = 2;
    $map[1][0][1][1][0][1][1] = 3;
    $map[0][1][1][1][0][1][0] = 4;
    $map[1][1][0][1][0][1][1] = 5;
    $map[1][1][0][1][1][1][1] = 6;
    $map[0][1][0][1][1][1][1] = 6;
    $map[1][0][1][0][0][1][0] = 7;
    $map[1][1][1][1][1][1][1] = 8;
    $map[1][1][1][1][0][1][0] = 9;
    $map[1][1][1][1][0][1][1] = 9;

    if(isset($map[$p[0]][$p[1]][$p[2]][$p[3]][$p[4]][$p[5]][$p[6]])) {
        return $map[$p[0]][$p[1]][$p[2]][$p[3]][$p[4]][$p[5]][$p[6]];
    }else{
        return false;
    }
}

Die (passend multiplizierten) Werte ergeben den Messwert. Die Erkennung ist zwar nicht 100%ig, jedoch bei der verfügbaren Auflösung wesentlich zuverlässiger als ein klassischer OCR und ausreichend um ein paar Kurven zu zeichnen. Derzeit werden etwa 80-90% der Captures erkannt. Die meisten Fehler kommen durch ungünstiges Timing – wenn die Kamera eine Aufnahme macht während die LED-Anzeige gerade aktualisiert kommt es zu halben Zahlen.

Bild: https://adlerweb.info/blog/wp-content/uploads/2014/08/Unbenannt.png

Arch Linux/Systemd: Screen-Sitzung als Daemon

Nicht immer kann oder möchte man ein Linux-Programm als Daemon starten – fehlende Daemon-Funktion, die Möglichkeit direkt auf STDOUT/STDERR zu schauen, etc. In den meisten Fällen bemühe ich für diese Fälle den Terminal Multiplexer „screen“. Hiermit wir die Software mit komplettem Terminal gestartet, man kann jedoch die Verbindung trennen, sodass das Programm im Hintergrund weiter seinen Dienst tut. Bei einem späteren Reconnect sind alle vorherigen Ausgaben wieder sichtbar.

Bisher startete ich diese Programme von Hand, auf einem System habe ich nun aber ein Shell-Script, welches sinnigerweise direkt beim Boot gestartet werden soll – bauen wir uns einen passenden Systemd-Service:

[Unit]
Description=Dynamic DNS updater
After=network.target

[Service]
RemainAfterExit=yes
User=root
ExecStart=/usr/bin/screen -AdmS ddns /usr/local/sbin/ddns.sh
ExecStop=/usr/bin/screen -S ddns -X quit

[Install]
WantedBy=multi-user.target

Wie unschwer zu erkennen handelt es sich um einen DDNS-Update-Daemon. Zwar würde der auch direkt laufen, da jedoch ab und an mal manuell ein Befehl abgesetzt werden muss ist mir screen lieber. Die Bedingung nach network.target zu laufen ist rein durch die DNS-Funktion bedingt und für Screen nicht notwendig.
Interessant wird es in [Service] – Erst wird der Nutzer festgelegt, welcher den Screen starten soll – da der Daemon Systemeinstellungen ändert komme ich hier um root nicht herum. Unter ExecStart wird der passende Befehl angegeben – es wird eine screen-Sitzung mit dem Namen „ddns“ gestartet und dort das Script „/usr/local/sbin/ddns.sh“ ausgeführt. In der nächsten Zeile wird zum Stoppen der Screen mit dem Namen „ddns“ beendet.

Die Datei wird unter /etc/systemd/system/ddns.service abgelegt und ist danach wie jeder andere Dienst nutzbar. Ist er mit „systemd start ddns“ gestartet kann der Nutzer root sich mittels „screen -x ddns“ zur laufenden Sitzung verbinden. Mit der Tastenkombination „Ctrl-a d“ wird die Verbindung wieder getrennt.

Einige Warnungen noch:
– Die Sitzung hat ggf. nicht alle Umgebungsvariablen, die man von einer „normalen“ Shell-Sitzung gewohnt ist
– Bricht das Script ab wird der Screen beendet, in dem Fall ist die Ausgabe/Fehlermeldung nicht mehr sichtbar. Hier kann man ggf. eine interaktive Shell nach dem Script starten und so die Sitzung offen halten. Beispiel:

ExecStart=/usr/bin/screen -AdmS ddns sh -c '/usr/local/sbin/ddns.sh ; bash'