Sonntag, 29. Juni 2014

PHP kann unter Mac OS X nicht mit MySQL kommunizieren

Da war ich am Donnerstag in den beeindruckenden neuen Räumlichkeiten meines ehemaligen Arbeitgebers Liip und nahm am Hackday teil, wo ich mich anfänglich mit der Konfiguration von Docker befasste — und war dann auf meinem MacBook Air in einem anderen Zusammenhang mit Verbindungsproblemen zwischen PHP und der MySQL-Datenbank konfrontiert.

PHPs mysqli meldete:

Error: 2002 - No such file or directory

Das Problem lag gemäss dieser Diskussion auf Stack Overflow darin begründet, dass ich nach dem Upgrade auf Mavericks die mitgelieferte php.ini unter /etc/php.ini verwendete, welche für Mac OS X nicht anwendbare Standardwerte für die Verbindung zu MySQL enthielt.

Nachdem ich die Einträge

...
pdo_mysql.default_socket=/var/mysql/mysql.sock
mysql.default_socket = /var/mysql/mysql.sock
mysqli.default_socket = /var/mysql/mysql.sock
...

in

...
pdo_mysql.default_socket=/tmp/mysql.sock
mysql.default_socket = /tmp/mysql.sock
mysqli.default_socket = /tmp/mysql.sock
...

geändert hatte und Apache mittels

# apachectl graceful

neugestartet hatte, sprach PHP problemlos mit MySQL.

Solche Handstände sind künftig nicht mehr nötig, da ich nun endlich meine Vagrant-Installation vom Mac mini hier auf das MacBook transferiert habe.

Tags: , , , ,
Labels: Uncategorized

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 29. Juni 2014

Kolonne A ist in Microsoft Excel kaum sichtbar

Ich verursachte im Büro kürzlich mit Excel einen Betriebsunfall: Auf den ersten Blick sah es zudem so aus, als wäre Kolonne A ausgeblendet worden. Doch alle Hantiererei brachte die Kolonne nicht mehr zum Vorschein. Nach etwas pröbeln realisiert ich, dass die Kolonne immer noch sichtbar war — aber einfach gefühlte 1 Pixel breit. Wenn ich in Kolonne B navigierte und die ausgewählte Zelle mit dem Tastencursor nach links bewegte, wurde der erwartete Wert der Kolonne A angezeigt. Die Spalte konnte aber nicht verbreitert werden. Was nun?

Google half, die Lösung aufzuzeigen:

From your worksheet menu click on Window > Unfreeze Panes. Then select any cell and hit the Home key.

Quelle: column A is missing. not hidden.

Danach war alles wieder gut.

Tags: , , , , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 29. Juni 2014

Die Chrome-Extension Send to Instapaper zurücksetzen

Vor kurzem habe ich die Passwortsicherheit zweier meiner Online-Accounts verbessert, unter anderem Instapaper.

Unter Google Chrome führte der Passwortwechsel aber zu einem Problem mit der Erweiterung “Send to Instapaper” (im Chrome Web Store finde ich sie aber irgendwie nicht (mehr) … hier die ID: liamajdghafnpofaconeimppimbdbhgi), mit welcher ich Artikel für eine spätere Lektüre zwischenspeichere: Bei jedem Klick auf den Button änderte sich dieser in ein rotes X, ohne mir die Möglichkeit anzubieten, das Passwort auszutauschen.

Nach einigem Googlen und pröbeln hatte ich dann die Lösung:

  • Unter Windows finden sich die Chrome-Erweiterungen im Verzeichnis C:\Users\<username>\AppData\Local\Google\Chrome\User Data\Default\Extensions\
  • Die besagte Erweiterung fand sich unter C:\Users\<username>\AppData\Local\Google\Chrome\User Data\Default\Extensions\liamajdghafnpofaconeimppimbdbhgi\1.2_0
  • Den “Local Store”, eine SQLite-Datenbank, welche die Erweiterung zur Ablage der Zugangsdaten verwendet, findet sich unter C:\Users\<username>\AppData\Local\Google\Chrome\User Data\Default\Local Storage\chrome-extension_liamajdghafnpofaconeimppimbdbhgi_0.localstorage sowie extension_liamajdghafnpofaconeimppimbdbhgi_0.localstorage-journal

Indem man Chrome schliesst, die zwei Dateien im Local Store löscht und Chrome danach wieder startet, wird man beim nächsten Klick auf den Button zur Eingabe der Zugangsdaten aufgefordert.

Tags: , , , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Freitag, 27. Juni 2014

Spam-Mails mit imapfilter in einen Unterordner verschieben

Der falsche Weg, wie ich ihn bis heute angewendet hatte:

...
-- SPAM
messages = mbox.INBOX:contain_subject('[SPAM]')
messages:move_messages(mbox['Spam'])
...

Das führte in diesem einen speziellen Fall dazu, dass ein legitimes E-Mail eines Kollegen mit “[SPAM]” im Subject gekennzeichnet wurde. Da das elektronische Gespräch hin- und herging, landeten alle Antworten des Empfängers immer wieder in meinem Spam-Ordner.

Der richtige Weg — jedenfalls für Mail-Accounts, die bei Cyon GmbH gehostet werden — ist:

...
-- SPAM
messages = mbox.INBOX:contain_field('X-Spam-Status','Yes')
messages:move_messages(mbox['Spam'])
...

Tags: , , , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Freitag, 27. Juni 2014

.ch-Domains zu cyon transferieren

Heute schreckte mich Blogging Tom auf Facebook mit der Meldung auf, dass SWITCH/nic.ch per 1. Januar 2015 keine .ch-Domains mehr verwaltet. Bis spätestens zu diesem Stichdatum müssen .ch-Domains zu privaten schweizerischen Anbietern gezügelt werden.

Ich besitze ein halbes Dutzend .ch-Domains und lasse diese bereits alle auf meinen Shared Server bei der Cyon GmbH in Basel zeigen. Zum Glück hat der dortige Support in seiner Knowledgebase bereits eine bebilderte und “dubelisichere” Anleitung aufgeschaltet, an Hand derer ich den Transfer innert 5 Minuten hingekriegt habe:

Wie kann ich meine Domain von SWITCH zu cyon transferieren?

ACHTUNG: Die ursprüngliche Google-Suche leitete mich auf folgenden Artikel, welcher diesen Spezialfall leider nicht behandelt:

Wie kann ich meine Domains transferieren?

Tags: , , , , , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 11. Juni 2014

FileVault 1 schrumpfen

Sicherheitsbewusste Mac-User werden das Phänomen kennen: Nach einigen Monaten wird das FileVault 1-Image eines Benutzerkontos fett und belegt trotz regelmässigen manuellen Säuberungsaktionen von Dateien und Ordnern (Disk Inventory X zu Hilfe!) unerklärbar viel Speicherplatz.

Apple verwendet das sogenannte .sparsebundle-Format, um die Daten im home-Verzeichnis eines Benutzers in einem verschlüsselten Image abzulegen. Das Image scheint die Eigenschaft zu haben Speicherplatz nicht immer automatisch freizugeben.

Dem kann Abhilfe geschafft werden:

  1. Über die Systemsteuerung einen zweiten Mac OS X-Benutzer einrichten
  2. Diesem Benutzer ist die Berechtigung zur Administration des Rechners zu geben
  3. Logout aus dem eigenen Konto
  4. Login in das zweite Konto
  5. Terminal öffnen
  6. $ sudo hdiutil compact /Users/.mario/mario.sparsebundle

    eingeben

  7. Logout aus dem fremden Konto
  8. Login in das eigene Konto

Nun könnte die Festplatte um einige Gigabytes leichter sein.

Problem

Führt man obiges Shell-Kommando auf einem Laptop durch, könnte einem folgende Fehlermeldung entgegengeworfen werden:

Initializing ...
Finishing ...
hdiutil: compact failed – Function not implemented

Ein grosses Bravo an Apple für völlig nutzlose, nichtssagende Fehlermeldungen! Die Ursache ist im Batteriebetrieb des Laptops zu suchen. Die Lösung des Problems ist deshalb die Verwendung der Option -batteryallowed:

$ sudo hdiutil compact /Users/.mario/mario.sparsebundle -batteryallowed

Quelle: Solution for hdiutil: compact failed – Function not implemented

Tags: , , , ,
Labels: Apple

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 11. Juni 2014

Schulferien in der Schweiz

Für einen motorisierten Wochenendausflug nach Deutschland interessierte mich eine Prognose der Verkehrssituation. TCS hilft weiter:

Verkehrsprognosen

Über einen Link stösst man dann sogar auf einen Kalender, welcher die Schulferien aller schweizerischen Kantone im aktuellen Jahr minutiös auflistet:

Schulferien und Feiertage

Erkenntnisse:

  • Der Kanton Aargau weist die kürzesten Sommerferien auf (19. Juli bis und mit 10. August – 3 Wochen)
  • Der Kanton Tessin (wenn verwundert’s?) zählt hingegen die längsten Ferien (18. Juni bis und mit 1. September – 6.5 Wochen)

Tags: , , ,
Labels: Leben, Schweiz

1 Kommentar | neuen Kommentar verfassen

Montag, 2. Juni 2014

MySQL will nach dem Upgrade auf Version 5.5 unter Debian nicht mehr starten

Aus irgendeinem Grund setze ich auf meinem Entwicklungsserver seit Jahren MySQL 5.0 ein. Heute sah ich den Tag gekommen, die Datenbank auf Version 5.5 zu “lüpfen”.

Leider lief dieses Unterfangen nicht ohne Komplikationen ab:

# /etc/init.d/mysql start
Starting MySQL database server: mysqld . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . failed!

Konfigurationsdatei anpassen

Na toll, sehr aussagekräftig das Ganze! Doch wenn man anstelle des Debian Startup-Scripts mysqld direkt aufruft, wird man von Fehlermeldungen nur so erschlagen:

# /usr/sbin/mysqld 
140602 21:39:51 [Warning] Using unique option prefix key_buffer instead of key_buffer_size is deprecated and will be removed in a future release. Please use the full name instead.
140602 21:39:51 [Warning] The syntax '--log-slow-queries' is deprecated and will be removed in a future release. Please use '--slow-query-log'/'--slow-query-log-file' instead.
140602 21:39:51 [ERROR] An old style --language value with language specific part detected: /usr/share/mysql/english/
140602 21:39:51 [ERROR] Use --lc-messages-dir without language specific part instead.
140602 21:39:51 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will be removed in a future release. Please use the full name instead.
140602 21:39:51 [Note] Plugin 'FEDERATED' is disabled.
/usr/sbin/mysqld: Table 'mysql.plugin' doesn't exist
140602 21:39:51 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
140602 21:39:51 InnoDB: The InnoDB memory heap is disabled
140602 21:39:51 InnoDB: Mutexes and rw_locks use GCC atomic builtins
140602 21:39:51 InnoDB: Compressed tables use zlib 1.2.8
140602 21:39:51 InnoDB: Using Linux native AIO
140602 21:39:51 InnoDB: Initializing buffer pool, size = 128.0M
140602 21:39:51 InnoDB: Completed initialization of buffer pool
140602 21:39:51 InnoDB: highest supported file format is Barracuda.
140602 21:39:51  InnoDB: Waiting for the background threads to start
140602 21:39:52 InnoDB: 5.5.37 started; log sequence number 3243771
140602 21:39:52 [ERROR] /usr/sbin/mysqld: unknown option '--skip-bdb'
140602 21:39:52 [ERROR] Aborting

140602 21:39:52  InnoDB: Starting shutdown...
140602 21:39:53  InnoDB: Shutdown completed; log sequence number 3243771
140602 21:39:53 [Note] /usr/sbin/mysqld: Shutdown complete

Soso. Zuerst einmal musste ich die Konfigurationsdatei /etc/mysql/my.cnf säubern — auch wenn obige Fehlermeldungen aussehen als würden sie von Kommandozeilenoptionen stammen, waren sie bei mir alle in der my.cnf spezifiziert.

  • key_buffer muss in key_buffer_size umbenannt werden
  • log_slow_queries muss in slow-query-log-file umbenannt werden
  • language = /usr/share/mysql/english muss vollständig auskommentiert werden
  • myisam-recover muss in myisam-recover-options umbenannt werden
  • skip-bdb muss vollständig auskommentiert werden

Tabellenstruktur aktualisieren

Nach dieser Aktion kam MySQL zwar nicht mehr hoch, aber spuckte immerhin nur noch eine Fehlermeldung aus:

...
mysqld: Table 'mysql.plugin' doesn't exist
140602 21:52:02 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
...

Wenn ich diesen Befehl aber auf der Kommandozeile ausführte, erhielt ich folgendes zu Gesicht:

# mysql_upgrade
Looking for 'mysql' as: mysql
Looking for 'mysqlcheck' as: mysqlcheck
FATAL ERROR: Upgrade failed

Eine Antwort auf Serverfault half mir dann aber auf die Sprünge: Bevor man diesen Befehl ausführt, muss mysql im Hintergrund laufen. Doch wie starte ich MySQL, wenn es zuerst die Ausführung von mysql_upgrade verlangt? Mit folgendem Befehl ignoriert MySQL Probleme mit fehlenden Tabellen:

# mysqld --skip-grant-tables

Anschliessend lässt man mysql_upgrade in einem anderen Terminal laufen. Und voila, nach dieser Aktion kommt MySQL nun auch wieder mit dem Debian-Startscript hoch:

# # /etc/init.d/mysql start
Starting MySQL database server: mysqld ..
Checking for tables which need an upgrade, are corrupt or were 
not closed cleanly..

Tags:
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 28. Mai 2014

AirPrint mit einem HP LaserJet 1300 auf einem Linux-Server aktivieren

Heute habe ich den Linux-Server in meinem Heimnetzwerk so konfiguriert, dass der dort per USB angeschlossene HP LaserJet 1300 auch von iOS-Geräten (iPhone und iPad) mittels AirPrint angesteuert werden kann.

Dies stellt sich heutzutage, anno 2014, als ein äusserst simples Unterfangen heraus:

CUPS installieren

Zuerst installiert man auf dem Server CUPS, das Common UNIX Printing System, welches von Apple gehegt und gepflegt wird. In meinem Fall hat dieses Drucksystem lprng ersetzt, welches automatisch deinstalliert wird:

# apt-get install cups

cups Web-Oberfläche freigeben

In /etc/cups/cupsd.conf sind in allen Location-Elementen (merke: CUPS verwendet Apache als Web-Frontend) die IPs des lokalen Netzwerks für erlaubte Zugriffe freizugeben:

...
Listen *:631
...
DefaultAuthType BasicDigest
...
<Location />
  Order allow,deny
  Allow From 10.0.10.0/24
</Location>
...
<Location /admin>
  Order allow,deny
  Allow From 10.0.10.0/24
</Location>
...

DefaultAuthType BasicDigest habe ich von Basic auf Digest umgestellt, damit ich das Passwort meines sudo-befähigten Benutzers nicht im Klartext über das Netzwerk gesendet wird. Damit man sich nach dieser Konfigurationsanpassung einloggen kann, muss man zuerst noch einen entsprechenden Benutzer erstellen:

# lppasswd -a <username>
Enter password: ********
Enter password again: ********

Eigener Benutzer der Gruppe lpadmin hinzufügen

Damit ich CUPS über die Web-Oberfläche administrieren kann, habe ich meinen persönlichen Benutzernamen zusätzlich der lokalen Gruppe lpadmin zugewiesen:

# usermod -aG lpadmin <username>

CUPS LPD-Druckserver einrichten

Obwohl heute IPP das Mass aller (Druck)dinge ist, verwende ich für Mac OS X- und Windows-Clients weiterhin das LPR/LPD-Druckprotokoll, weil es so simpel gestrickt und kaum fehleranfällig ist. Da CUPS aber lprng deinstalliert hat, muss in /etc/inetd.conf folgende Zeile eingefügt werden, welche den CUPS-eigenen LPD-Server aktiviert:

...
printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd -o document-format=application/octet-stream

inetd startet man unter Debian folgendermassen neu:

# /etc/init.d/openbsd-inetd restart

Drucker einrichten und konfigurieren

Über die Web-Oberfläche, welche man unter http://localhost:631 erreicht (respektive über http://10.0.10.10:631) richtet man sich mit dem Installationsassistenten den USB-Drucker ein. Bei mir wurde das Gerät an der USB-Schnittstelle problemlos erkannt und auch entsprechende HP-Treiber angeboten.

WICHTIG: Ich hatte erhebliche Probleme mit dem Postscript-Druckertreiber (der HP LaserJet 1300 kann Postscript 2 emulieren): Jeder zweite Druckauftrag — egal ob von Mac oder vom iPad — blockierte den Drucker entweder oder liess ihn eine fast leere Seite mit der Fehlermeldung “Offending Command” ausdrucken. Doch sobald ich den Drucker auf den Sample monochrome PCL XL/PCL 6 driver umgestellt hatte, funktionierte die Druckerei tadellos. In diesem Fall ist aber darauf zu achten, dass man unter Mac OS X ebenfalls mit dem PCL-Druckertreiber druckt, damit man dem CUPS-Druckserver die Umwandlung von PostScript zu PCL erspart.

Fertig!

Obwohl ältere AirPrint-Installationsanleitungen im Internet die Sysadmins nun auch noch auffordern, Avahi zu installieren (war bei mir schon vor dieser Neukonfiguration des Drucksystems auf dem Server aktiv) und mittels des Scripts airprint-generate.py einen Bonjour-Service anzukündigen, funktionierte die Anpreisung mit CUPS 1.7.2-3 ohne irgendwelche Konfigurationsanpassungen.

Tags: , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 25. Mai 2014

Einem mit puPHPet aufgesetztem Vagrant schreibenden Zugriff auf das synchronisierte wwwroot des Host-Systems geben

Das Web ist voll von Diskussionen zu diesem Thema, und einige Tipps erfordern zeitintensive Eingriffe in die Konfiguration:

Folgende Konfigurationsanpassung in der Vagrantfile-Konfigurationsdatei hat bei mir das Problem gelöst, dass Apache im VMBox-Container nicht in das synchronisierte wwwroot auf meinem Mac OS X-Host schreiben konnte:

...
data['vm']['synced_folder'].each do |i, folder|
    if folder['source'] != '' && folder['target'] != ''
      nfs = (folder['nfs'] == "true") ? "nfs" : nil
      if nfs == "nfs"
        config.vm.synced_folder "#{folder['source']}", "#{folder['target']}", id: "#{i}", type: nfs
      else
        config.vm.synced_folder "#{folder['source']}", "#{folder['target']}", id: "#{i}", type: nfs,
          group: 'www-data', user: 'www-data', mount_options: ["dmode=777", "fmode=777"]
      end
    end
  end
...

Mit dem Parameter mount_options: ["dmode=777", "fmode=777"] schreiben die Web-Applikationen ihre Cache-Dateien munter und fröhlich in das wwwroot des Host-Systems.

Und ja, mir ist ehrlich gesagt schnurz, wenn die Entwickler ideologisch-religiöse Gründe vorbringen, wieso dies eine ganz, ganz schlechte Idee ist … ich verwende Vagrant, um genau solchen Konfigurationsalpträume aus dem Weg zu gehen und innert Minuten auf all meinen Entwicklungssystemen eine homogene Entwicklungsumgebung zu haben.

Etwas gutes hatten die Probleme aber: Ich habe eine meiner Web-Applikationen so angepasst, dass sie nun beim Starten auch prüft, ob sie überhaupt Schreibberechtigung auf das Cache-Verzeichnis hat.

Labels: Uncategorized

Keine Kommentare | neuen Kommentar verfassen