Donnerstag, 20. Juli 2017

Apache nervt mit Warnmeldungen, dass das DAV-Modul bereits geladen sei

Seit Jahr und Tag nerve ich mich ab Log-Zeilen in der folgenden Form, welche im syslog und in E-Mail-Nachrichten zu cron-Jobs auftauchen:

[Mon Jul 17 06:25:06.171427 2017] [so:warn] [pid 724] AH01574: module dav_module is already loaded, skipping

Und zwar immer dann, wenn Apache 2.4 neu gestartet wird (bspw. mittels apache2ctl graceful).

Lustigerweise findet sich im Netz keine Lösung des Problems — ein Novum, das mich daran zweifeln lässt, ob neben mir überhaupt noch jemand mit diesem nervigen Problem zu kämpfen hat.

Ich habe bereits mehrere Anläufe genommen, um im Netz eine Lösung zu dem Problem zu finden. Doch erst beim gefühlten Dutzendsten Versuch fand ich tief versteckt in den Google-Resultaten dann doch noch die Lösung:

# error at apache2 startup
    AH01574: module dav_module is already loaded, skipping
# solution; edit /etc/apache2/mods-available/dav.load
    <IfModule !mod_dav.c>
        LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so
    </IfModule>

Quelle: adrhc’s blog (ACHTUNG: Zertifikatsfehler!)

Geniale Idee des Kollegen aus Rumänien (der TLD nach zu urteilen): Indem man den Inhalt der Datei /etc/apache2/mods-available/dav.load in eine IfModule-Abfrage packt, verhindert man, dass mod_dav ein zweites Mal geladen wird.

Seither ist Ruhe.

Was ich hingegen immer noch nicht weiss: Wo mod_dav zum ersten Mal geladen wird. Ich fand keine zweite Lade-Anweisung irgendwo in den Konfigurationsdateien unterhalb von /etc/apache2.

Tags: , , , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 5. Juli 2017

Properties und Methoden eines PowerShell-Objektes anzeigen

Ich programmiere zwar seit einigen Jahren hie und da PowerShell-Scripts, aber bis heute wusste ich nicht, dass man Properties und Methoden eines PowerShell-Objektes derart einfach ausgeben kann. Die Web-Site msXfaq.de half weiter.

Properties

$var = Get-Date
$var | fl *
DisplayHint : DateTime
DateTime    : Dienstag, 29. Oktober 2013 00:16:08
Date        : 29.10.2013 00:00:00
Day         : 29
DayOfWeek   : Tuesday
DayOfYear   : 302
Hour        : 0
Kind        : Local
Millisecond : 229
Minute      : 16
Month       : 10
Second      : 8
Ticks       : 635186025682291672
TimeOfDay   : 00:16:08.2291672
Year        : 2013

Methoden

$var = Get-Date
$var | gm *
TypeName: System.DateTime

Name                 MemberType     Definition
----                 ----------     ----------
Add                  Method         datetime Add(timespan value)
AddDays              Method         datetime AddDays(double value)
AddHours             Method         datetime AddHours(double value)
AddMilliseconds      Method         datetime AddMilliseconds(double value)
AddMinutes           Method         datetime AddMinutes(double value)
AddMonths            Method         datetime AddMonths(int months)
AddSeconds           Method         datetime AddSeconds(double value)
AddTicks             Method         datetime AddTicks(long value)
AddYears             Method         datetime AddYears(int value)
CompareTo            Method         int CompareTo(System.Object value), int CompareTo(datetime value), int IComparable.CompareTo..
Equals               Method         bool Equals(System.Object value), bool Equals(datetime value), bool IEquatable[datetime].Equ..
IsDaylightSavingTime Method         bool IsDaylightSavingTime()
Subtract             Method         timespan Subtract(datetime value), datetime Subtract(timespan value)
ToFileTime           Method         long ToFileTime()
ToFileTimeUtc        Method         long ToFileTimeUtc()
ToLocalTime          Method         datetime ToLocalTime()
ToLongDateString     Method         string ToLongDateString()
ToLongTimeString     Method         string ToLongTimeString()
ToOADate             Method         double ToOADate()
ToSByte              Method         sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToShortDateString    Method         string ToShortDateString()
ToShortTimeString    Method         string ToShortTimeString()
ToString             Method         string ToString(), string ToString(string format), string ToString(System.IFormatProvider pr..
ToUniversalTime      Method         datetime ToUniversalTime()
DisplayHint          NoteProperty   Microsoft.PowerShell.Commands.DisplayHintType DisplayHint=DateTime
Date                 Property       datetime Date {get;}
Day                  Property       int Day {get;}
DayOfWeek            Property       System.DayOfWeek DayOfWeek {get;}
DayOfYear            Property       int DayOfYear {get;}
Hour                 Property       int Hour {get;}
Kind                 Property       System.DateTimeKind Kind {get;}
Millisecond          Property       int Millisecond {get;}
Minute               Property       int Minute {get;}
Month                Property       int Month {get;}
Second               Property       int Second {get;}
Ticks                Property       long Ticks {get;}
TimeOfDay            Property       timespan TimeOfDay {get;}
Year                 Property       int Year {get;}

Tags: , , , , ,
Labels: Programmierung

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 5. Juli 2017

Mit PowerShell ein Datum in einem spezifischen Format ausgeben

Heute habe ich an einem PowerShell-Script gearbeitet, welches Active Directory abfrägt und mir eine Liste von Benutzern ausgibt, die meinem Filter entsprechen.

Dabei interessierte mich auch das Attribut WhenCreated, welches angibt, wann ein Benutzerkonto erstellt wurde.

Mit dem Ausgabeformat dieses Feldes, welches als Datums-Objekt verarbeitet wird, war ich nicht zufrieden.

Doch wie gebe ich das Datum in einem von mir gewünschten Format aus? Nicht gerade trivial, aber es klappt:

...
$whenCreated = $objUser.whencreated
$whenCreate.GetDateTimeFormats()
...

So gibt man alle erdenklichen Variationen von Datumsformaten des aktuellen Datums-Objektes zurück. Nun muss man in der Liste nur noch die Zeilennummer des passenden Datumsformats finden, und integriert es dann folgendermassen in den Code. Ich habe mich dabei für die YYYY-MM-DD 00:00-Notation entschieden, welche in Zeile 103 ausgegeben wird:

...
$whenCreated = $objUser.whencreated
$whenCreatedFormatted = $whenCreate.GetDateTimeFormats()[103]
...

Via: How to format a DateTime in PowerShell?

Tags: , ,
Labels: Programmierung

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 2. Juli 2017

Stockende Texteingabe in Web-Formularen mit hunderten HTML Input-Elementen unter Safari

Seit einigen Monaten (wahrscheinlich als Kollateralschaden eines Safari-Updates) habe ich ein Problem mit einer selber geschriebenen Web-Applikation: Die Eingabe von Zeichen in Textfelder eines Web-Formulars ist extrem langsam.

Zuerst verdächtigte eine veraltete jQuery-Bibliothek und onkeyup– und onblur-Attribute als Ursache, doch ein Update von jQuery hat keine Abhilfe geschafft.

Heute reichte es mir, und ich nahm erneut einen Anlauf, das Problem einzugrenzen. Eine Google-Suche förderte schnurstracks Probleme mit Safari unter iOS zu Tage, welche vor einigen Jahren bestanden (oder immer noch bestehen). Dies führte mich auf die Spur eines Stackexchange-Artikels, der identisches Verhalten auch in Safari unter macOS berichtete:

Safari on Mac responses slow when typing on a webpage with lots of <input type=“text”> fields

Das liess mich aufhorchen — denn die Applikation zeigt zwar nicht gerade hundert Eingabefelder an, doch in mehreren HTML-Tabellen werden alle Inhalte von Datenbank-Tabellen aufgelistet, woraus der Benutzer mit einem Klick auf einen Formular-Button den gewünschten Datensatz auswählen kann. Auf der Seite finden sich deshalb problemlos einige hundert input[button]-Elemente.

Könnte es sein, dass diese Elemente Safari spürbar langsamer machen? Ja!

Meine Lösung: Ich habe die Formular-Buttons in der Liste mit hinterlegtem JavaScript onclick mit HTML-Anchors ersetzt:

<a href="javascript:clicked();">wählen</a>

Seither fühlt sich der Browser wieder wie 2017 an, und nicht wie Netscape von 1998.

Tags: , , , , , ,
Labels: Apple

Keine Kommentare | neuen Kommentar verfassen

Samstag, 1. Juli 2017

Debian von einem bootbaren USB-Stick installieren

Kürzlich ist Debian 9.0 Stretch erschienen. Zeit, meinen USB-Stick mit den neuesten Installationsdateien zu bestücken, um zukünftige Linux-PCs von diesem Stick aus aufsetzen zu können.

Hierzu habe ich mir das neueste Debian Netinst ISO (für „Netzwerk-Installation“) heruntergeladen, welches man hier findet:

Debian — Network install from a minimal CD

Anschliessend habe ich den USB-Stick an meinen Mac mini eingesteckt (muss zwingend vor dem Starten von unetbootin gemacht werden, da das Drop-Down der Zielvolumes sonst leer bleibt), das bereits installierte unetbootin gestartet, das ISO ausgewählt und danach auf den USB-Stick kopieren lassen. Fertig.

Mangels eines verfügbaren, leeren Geräts konnte ich den Stick noch nicht testen, dieses Prozedere hat aber mit Debian 8.3 (Jessie) bereits perfekt funktioniert.

Tags: , , , , , , , , , ,
Labels: IT, Linux

Keine Kommentare | neuen Kommentar verfassen

Donnerstag, 22. Juni 2017

monit bei einem HTTP-Fehler keinen Alarm absetzen lassen

In der Standardkonfiguration meldet monit einen Alarm, wenn ein HTTP-Check eines Web-Servers eine HTTP-Response grösser/gleich 400 zurück gibt:

If not used, the http protocol test will fail if the status code returned is greater than or equal to 400. You can override this behaviour by using the status qualifier.

Quelle: Monit Version 5.23.0 — HTTP

Was aber, wenn eine HTTP-Response mit einem solchen Code das korrekte Funktionieren eines Web-Servers signalisiert und deshalb keinen Alarm generieren soll? Es gibt Abhilfe:

...
check host web.server.strasse.emeidi.local with address 10.10.10.10
if failed
   port 80
   protocol http
   request "/non/existent.php"
   status = 404
then alert
...

Quelle: Monit monitor http status with 404 page

Mittels des Keywords status = 000 gibt man an, was der tatsächlich erwartete Wert ist.

Tags: ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Donnerstag, 22. Juni 2017

Wenn Embedded Linux-Geräte kein HTTP HEAD verstehen

Netzwerkgeräte in meinem Intranet überwache ich mit der quelloffenen Software monit. Seit ich einen meiner monit-Server auf Debian Stretch upgegradet habe, häuften sich „Geister“-Fehlermeldungen — immer in Bezug auf Checks, welche die Verfügbarkeit von Web-Oberflächen abfragen. Dies in folgender Form:

...
check host web.server.strasse.emeidi.local with address 10.10.10.10
    if failed port 80 protocol http for 10 cycles then alert
...

Mit dem Upgrade auf Debian Stretch wird auch monit von Version 5.9-1+deb8u1 auf Version 5.20.0-6 aktualisiert.

Ich wartete also den Moment ab, in welchem ich per E-Mail die Fehlermeldung erhielt, loggte mich per SSH auf den Server ein und führte zu Debugging-Zwecken eine Abfrage aus — die Idee war, auf dem selben Server die Abfrage zu simulieren, die monit gegen das entfernte System laufen lässt:

$ wget --server-response "http://10.10.10.10/"
--2017-06-22 22:05:25--  http://10.10.10.10/
Verbindungsaufbau zu 10.10.10.10:80 … verbunden.
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 
  HTTP/1.1 200 OK
  Server: Router Webserver
  Connection: close
  Content-Type: text/html
  WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"
Länge: nicht spezifiziert [text/html]
Wird in »index.html« gespeichert.

index.html                   [ <=>                              ]   7,66K  --.-KB/s    in 0,01s   

2017-06-22 22:05:25 (754 KB/s) - »index.html« gespeichert [7841]

Dies funktioniert problemlos. Was Cheibs?

Als ich mir die Dokumentation zu monit genauer anschaute, realisierte ich eine feine, aber entscheidende Option:

PROTO(COL) HTTP
     [USERNAME "string"]
     [PASSWORD "string"]
     [REQUEST "string"]
     [METHOD <GET|HEAD>]
     [STATUS operator number]
     [CHECKSUM checksum]
     [HTTP HEADERS list of headers]
     [CONTENT < "=" | "!=" > STRING]

Quelle: Monit Version 5.23.0 — HTTP

Mit [METHOD ] entscheidet man, ob man einen normalen HTTP-Request („GET“) versendet, oder aber nur einen „HEAD“-Request, der nur nach dem Header einer Web-Site frägt. Das spitzfindige an der Sache:

METHOD set the HTTP request method. If not specified, Monit prefers the HTTP HEAD request method to save bandwidth, unless a response content or response checksum is tested. As some webservers may not support the HEAD method, one may want to set the method explicitly.

Dann lass uns das doch mal so simulieren. wget verfügt über die entsprechende Option --spider, die HEAD-Requests versendet:

$ wget --spider --server-response "http://10.10.10.10/"
Spider-Modus eingeschaltet. Es wird geprüft, ob die Datei auf dem Server existiert.
--2017-06-22 22:04:36--  http://10.10.10.10/
Verbindungsaufbau zu 10.10.10.10:80 … verbunden.
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 
  HTTP/1.1 501 Not Implemented
  Server: Router Webserver
  Connection: close
  WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"
  Content-Type: text/html
--2017-06-22 22:04:37--  (Versuch: 2)  http://10.10.10.10/
Verbindungsaufbau zu 10.10.10.10:80 … verbunden.
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 
  HTTP/1.1 200 OK
  Server: Router Webserver
  Connection: close
  Content-Type: text/html
  WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"
Länge: nicht spezifiziert [text/html]
Datei auf dem Server existiert und könnte weitere Verweise enthalten,
aber Rekursion ist abgeschaltet -- kein Download.

Via: Wget HEAD request?

Et voilà, das war das Problem: Der Embedded Web Server auf dem zu überwachenden Gerät hat Probleme, wenn aus dem nichts ein HEAD-Request kommt. Beim zweiten Anlauf dann ist die Web-Seite offenbar gerendert und der HEAD-Request kann beantwortet werden.

monit scheint nun aber offenbar so programmiert zu sein, dass nach dem ersten Versuch und einer Antwort mit Fehlern kein zweiter Versuch lanciert wird. Deshalb auch die sporadischen Fehlermeldungen.

Wie löst man das Dilemma? Ich wandelte den Test folgendermassen um:

...
check host web.server.strasse.emeidi.local  with address 10.10.10.10
    if failed
	port 80
	protocol http
	with content = "Willkommen"
	for 10 cycles
    then alert
...

Die Anweisung with content = "Zeichenkette" forciert monit, einen GET-Request abzusetzen und keinen HEAD (da nur beim GET-Request ein HTTP-Body mitgeliefert wird). Und schwup, Problem gelöst.

Erweitert

Übrigens: Wem die Ausgabe von wget noch nicht ausreicht, da sie zu wenig geschwätzig ist, kann auch die Debug-Option verwenden:

$ wget --debug --spider --server-response "http://10.10.10.10/"
Setting --spider (spider) to 1
Setting --server-response (serverresponse) to 1
DEBUG output created by Wget 1.19.1 on darwin15.6.0.

Reading HSTS entries from /Users/user/.wget-hsts
Converted file name 'index.html' (UTF-8) -> 'index.html' (UTF-8)
Spider-Modus eingeschaltet. Es wird geprüft, ob die Datei auf dem Server existiert.
--2017-06-22 22:02:44--  http://10.10.10.10/
Verbindungsaufbau zu 10.10.10.10:80 … verbunden.
Created socket 4.
Releasing 0x00007ff99bc231e0 (new refcount 0).
Deleting unused 0x00007ff99bc231e0.

---request begin---
HEAD / HTTP/1.1
User-Agent: Wget/1.19.1 (darwin15.6.0)
Accept: */*
Accept-Encoding: identity
Host: 10.10.10.10
Connection: Keep-Alive

---request end---
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 
---response begin---
HTTP/1.1 501 Not Implemented
Server: Router Webserver
Connection: close
WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"
Content-Type: text/html

---response end---

  HTTP/1.1 501 Not Implemented
  Server: Router Webserver
  Connection: close
  WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"
  Content-Type: text/html
Closed fd 4
--2017-06-22 22:02:48--  (Versuch: 2)  http://10.10.10.10/
Verbindungsaufbau zu 10.10.10.10:80 … verbunden.
Created socket 4.
Releasing 0x00007ff99bc23110 (new refcount 0).
Deleting unused 0x00007ff99bc23110.

---request begin---
GET / HTTP/1.1
User-Agent: Wget/1.19.1 (darwin15.6.0)
Accept: */*
Accept-Encoding: identity
Host: 10.10.10.10
Connection: Keep-Alive

---request end---
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 
---response begin---
HTTP/1.1 200 OK
Server: Router Webserver
Connection: close
Content-Type: text/html
WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"

---response end---

  HTTP/1.1 200 OK
  Server: Router Webserver
  Connection: close
  Content-Type: text/html
  WWW-Authenticate: Basic realm="TP-LINK Wireless Dual Band Gigabit Router WDR3600"
Länge: nicht spezifiziert [text/html]
Closed fd 4
Datei auf dem Server existiert und könnte weitere Verweise enthalten,
aber Rekursion ist abgeschaltet -- kein Download.

Via: What headers are automatically send by wget?

Sackgassen

Initial befürchtete ich, dass der Web-Server des Zielsystems sich am User-Agent des Requests verschluckt. Doch dies war eine falsche Vermutung. Nichtdestotrotz könnte man monit so konfigurieren, dass es einen alternativen User-Agent sendet:


‚User-Agent‘ header can not be set via ‚http headers‘ array

Und noch ein anderes Beispiel: Trying to configure monit to use https protocol but it sticks with http

Tags: , , , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Freitag, 16. Juni 2017

Icon zum PDF-Export in Word aktivieren

Auf der Arbeit bevorzuge ich es, PDFs anstelle von Word-Dateien zu versenden.

Damit das ohne langes herumhangeln in Menus funktioniert, habe ich mir in der Quick Access Toolbar einen Button platziert, der dies auf Knopfdruck bewerkstelligt.

Vorgehen:

  1. Rechtsklick auf Quick Access Toolbar
  2. Customize
  3. Choose commands from: All Commands
  4. Publish as PDF or XPS
  5. Klick auf „Add > >“
  6. OK

Quelle: save file as a .pdf shortcut for Word 2013

image-7357

image-7358

Tags: , , , , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Freitag, 16. Juni 2017

iPhone-Halterung von Oral-B Genius 8000 hält nicht mehr

Seit dem 8. November 2016 steht in unserem Haushalt eine elektrische Zahnbürste namens Oral-B Genius 8000S White.

Das Ding hat Bluetooth integriert und schwatzt während dem Zähneputzen mit meinem Smartphone. Das Smartphone wiederum ist an einer Halterung mit Saugnapf an der Badezimmerwand angebracht und überwacht mit laufender Front-Kamera, wo im Mund sich die Zahnbürste gerade befindet. Die App stellt dann sicher, dass ich jeden der sechs Zahnbereiche ausreichend lange putze.

Es scheint zu nützen — beim letzten Besuch bei der Dentalhygiene konnte ich meinen Karies-Anteil von über 20 Prozent auf 16 Prozent senken (Zahlen ohne Gewähr). Selbstverständlich ist das keine wissenschaftliche Feststellung, andere Faktoren könnten eventuell auch zu diesem Resultat beigetragen haben. Wir werden über die nächsten Besuche hinweg sehen, ob der Trend anhält.

Wie dem auch sei, seit der Rückkehr aus Island haftet der Saugnapf der Halterung nicht mehr sauber an der Wand. Mein iPhone ist deswegen bereits mehrmals aus ein Meter fünfzig Höhe auf den Plattenboden im Badezimmer gedonnert — glücklicherweise ohne bleibende Schäden für das Telefon. Der Badezimmerteppich hat den Aufprall jeweils abgedämpft.

Im Netz habe ich mich schlau gemacht darüber, wie man einen Saugnapf wieder haftbarer macht. Ohne Erfolg! Probiert habe ich bisher:

Die Suche nach einer permanenten Lösung geht weiter …

Tags: , , , , ,
Labels: Shopping

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 21. Mai 2017

Packlisten für Island

Unsere erste Reise nach Island steht vor der Tür, weshalb wir heute nicht das schöne Wetter in der Schweiz genossen haben, sondern primär unsere Koffern gepackt haben.

Geholfen haben uns einige Web-Seiten und YouTube-Videos, welche man eigentlich auf folgende Empfehlung komprimieren kann: Schichten, Schichten, Schichten. Und vielleicht auch noch: Baumwolle (bspw. Jeans) sind böse, da sie viel zu lange brauchen, um zu trocknen.

Zurück zum Schichtprinzip. Unser Vorteil: Als wanderaffiner Schweizer hat man die Funktionsbekleidung längst im Haus und man muss sie somit nur noch in den Koffer packen.

Das einzige, was mir wirklich fehlt: Regenhosen. Ich dachte ich hätte solche das letzte Mal getragen als ich mich das letzte Mal mit dem Velo von zu Hause in die Sek Neuenegg gemacht habe. Falsch gedacht.

Web-Seiten

Videos

Tags: , , ,
Labels: Reisen

Keine Kommentare | neuen Kommentar verfassen