Archiv ‘Linux’

Mittwoch, 5. März 2014

UUID einer Festplatte unter Linux auslesen

Es empfiehlt sich heutzutage, in /etc/fstab die Festplatten basierend auf ihrer UUID am richtigen Mount-Point einzuhängen. Die UUID einer bestimmten Platte findet man auf folgenden zwei Wegen heraus:

$ ls -l /dev/disk/by-uuid

Oder wenn die Device-Bezeichnung der Festplatte bekannt/klar ist:

$ blkid /dev/sda

Quelle: Short Tip: Get UUID of Hard Disks [Update]

Tags: , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 5. März 2014

Alle Spuren von GPT-Partitionen von einer portablen Festplatte entfernen

Ich habe eine kürzlich erworbene Festplatte mit dem Disk Utility von Mac OS X komplett neu formatiert und partitioniert. Als ich die Festplatte kürzlich unter Linux neu partitionieren wollte, realisierte ich, dass die Festplatte mit den neuen GPT-Partitionen eingerichtet war (im Gegensatz zu den aus der DOS-Zeit stammenden MBR-Partitionen).

Wie entfernt man jegliche Überreste von GTP-Partitionierungsschemen von der Festplatte? Ganz einfach: Man installiere sich das Debian-Paket gdisk und führe dann folgendes aus:

# apt-get install gdisk
# gdisk /dev/sde
GPT fdisk (gdisk) version 0.7.2

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: present

Found valid MBR and GPT. Which do you want to use?
 1 - MBR
 2 - GPT
 3 - Create blank GPT

Your answer: 1

Command (? for help): x

Expert command (? for help): z
About to wipe out GPT on /dev/sde. Proceed? (Y/N): y
GPT data structures destroyed! You may now partition the disk using fdisk or
other utilities.
Blank out MBR? (Y/N): n
MBR is unchanged. You may need to delete an EFI GPT (0xEE) partition
with fdisk or another tool.

Quelle: Wiping Out Old GPT Data

Tags: , , , , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 26. Januar 2014

Shell-Script-Befehl auf STDOUT ausgeben und danach ausführen

Viele meiner Scripts sind mit hoher Verbosität programmiert, damit ich während der Entwicklung weiss, wo allfällig die Ausführung abbricht. Hierzu gehört auch, dass ich komplexe Befehle vor der Ausführung ausgebe. Damit kann ich den Befehl kopieren und beim Debugging manuell auf der Kommandozeile ausführen, um vielleicht weitere Hinweise auf das Problem zu erhalten.

Doch wie macht man das, wenn man bspw. bei rsync Pfadangaben mit Leerschlägen drin hat, die vom Tool dann auch effektiv erkannt und verarbeitet werden sollen? Hier die Lösung:

...
$SOURCE="/Users/mario/Pictures/iPhoto Library/"
$DEST="/Volume/Sicherungs Ordner mit vielen Leerzeichen/"
...
COMMAND="rsync $OPTS \"$SOURCE\" \"$DEST\""
...
echo "Executing '$COMMAND' ..."
...
eval $COMMAND
...

Die ganze Chose steht und fällt mit eval. Wird nur $COMMAND ausgeführt, stolpert rsync über die ordentlich mit Anführungszeichen versehenen Pfade mit Leerzeichen.

Tags: , , , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 26. Januar 2014

Shell-Scripte mit vielen Optionen

Komplexe Shell-Scripte, welche ein Unix-Tool mit unzähligen Optionen aufrufen, muss man ab und zu debuggen. Damit dies möglichst einfach funktioniert, habe ich mir angewöhnt, die Optionen so zu notieren, damit ich jede einzelne Option mit einem Tastendruck auskommentieren kann:

...
OPTS=""
OPTS="$OPTS --verbose"
OPTS="$OPTS --archive"
OPTS="$OPTS --no-owner"
OPTS="$OPTS --no-group"
#OPTS="$OPTS --delete" # WILL DESTROY EVERYTHING! DO NOT UNCOMMENT
OPTS="$OPTS --progress"
...
rsync $OPTS "$SOURCE" "$DESTINATION"
...

Tags: , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 26. Januar 2014

Das Mac OS X Home-Verzeichnis mit rsync über SSH auf eine Synology Diskstation sichern

Nachdem ich den schlüsselbasierten Login hingekriegt hatte, stand ich bereits wieder vor dem nächsten Problem: Mein rsync-Script zur Sicherung meines Mac OS X Home-Verzeichnis in einen Unterordner auf meinem Home-Verzeichnis auf dem Synology NAS brach mit folgender Fehlermeldung ab:

...
rsync: writefd_unbuffered failed to write 4 bytes to socket [sender]: Broken pipe (32)
ERROR: module is read only
...

Wieso denn das? Mit dem Synology-Konto meines Raspberry Pi klappt die ganze Chose problemlos!

Mit den Hinweisen unter Rsync over ssh: “ERROR: module is read only” suddenly appeared wurde ich auf den richtigen Pfad gelenkt: Ich musste meinem Benutzer mittels des Synology Web-GUIs Schreibrechte auf den Homes-Ordner geben:

  1. Control Panel
  2. Users
  3. %BENUTZER% auswählen
  4. Edit
  5. Privileges Setup
  6. homes
  7. [x] Read/Write
  8. OK

Seither klappt die rsync-Synchronisierung. Ob ich aber damit eine Sicherheitslücke geöffnet habe?

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

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 26. Januar 2014

Sich schlüsselbasiert per SSH auf einer Synology Diskstation einloggen

Im Grunde ein einfaches Unterfangen, welches im Internet auf unzähligen Seiten dokumentiert ist. Kurzfassung: Auf dem eigenen Arbeitsrechner einen privaten und öffentlichen Schlüssel erstellen, auf der Synology Diskstation den SSH-Zugang aktivieren, eine Login-Shell einrichten und dort dann unter ~/.ssh/authorized_key den öffentlichen Schlüssel ablegen.

Was ich vor einigen Monaten mit meinem Raspberry Pi erfolgreich und innert kurzer Zeit hingebracht habe, wollte mich gestern während eineinhalb Stunden auf Trab halten. Neu wollte ich auch meinen persönlichen Account mit einem schlüsselbasierten SSH-Zugang ausstatten. Doch während der schlüsselbasierte Login mit dem Raspberry Pi-Konto problemlos funktionierte, wollte es mit dem privaten Konto einfach nicht klappen, obwohl die Konfiguration identisch war.

Lösung

Die nach unzähligen Pröbelversuchen eruierte Ursache: Das Home-Directory meines Benutzers war nicht mit den korrekten Berechtigungen versehen:

VAULT> ls -l /volume1/homes/     
...
drwxrwxrwx    6 mario    users         4096 Jan 26 10:42 mario
...

Nachdem ich folgenden Befehl ausgeführt hatte, klappte es plötzlich:

$ chmod 755 /volume1/homes/mario

Hierbei handelt es sich um eine im Grunde gut gemeinte Sicherheitsvorkehrung auf Unix-Systemen. Denn wenn andere Benutzer den Public Key eines anderen Benutzers ersetzen könnten, könnten sie sich anschliessen unter dessen Kontext einloggen.

Siehe auch der Beitrag SSH and home directory permissions auf Stackexchange.

Hintergründe

Ein grosses Problem dieser Synology-Box ist es, dass auf ihr ein abgespecktes Linux läuft, welches einerseits die gängigsten Debug-Optionen nicht zur Verfügung stellt (bspw. ein sauberes Logging der Aktivitäten von sshd), andererseits über eine schier unüberschaubare verschachtelte Konfiguration verfügt.

sshd_config

Insgesamt habe ich auf der Kiste drei sshd_config Konfigurationsdateien gefunden:

  • /etc/ssh/sshd_config
  • /etc.defaults/ssh/sshd_config
  • /usr/syno/etc.defaults/ssh/sshd_config

Welche ist nun die richtige? Und welche bleibt auch bei einem Update oder Neustart mit meinen Konfigurationsanpassungen bestehen? Ich weiss es bis heute nicht.

sshd neu starten

Auch hierfür gibt es mehrere Möglichkeiten. Im Netz habe ich zwei Befehle gefunden:

  • # killall sshd
  • # /usr/syno/etc.defaults/rc.d/S95sshd.sh restart

Wenn ich diese Befehle ausgeführt habe, bin ich natürlich schnurstracks aus der SSH-Session geflogen — logisch. Doch bei der Verwendung von killall hat man sich soeben gerade vollständig vom NAS ausgesperrt.

Glücklicherweise gibt es über das Web-GUI des NAS die Möglichkeit, SSH wieder zu starten:

  1. Control Panel
  2. Terminal
  3. [x] Enable SSH service

Was ich zudem auch realisiert habe: Wenn ich SSH über das GUI neu starte, wird /etc/ssh/sshd_config neu eingelesen. Wenn ich es mit den Kommandozeilenbefehlen neu starte, wird die Konfigurationsdatei irgendwie nicht beachtet …

Verschachtelte Start-Scripts

Wie genau wird nun aber SSH gestartet? Die Synology-Ingenieure haben sich wohl gesagt: “Wieso einfach, wenn es auch kompliziert geht?” und sich einige verschachtelte Scripts geleistet:

/usr/syno/etc.defaults/rc.d/S95sshd.sh liest einerseits /etc.defaults/rc.subr als auch /usr/syno/etc.defaults/rc.ssh.subr ein. Gestartet wird der SSH-Daemon dann aber, indem das Script /usr/syno/etc.defaults/rc.ssh aufgerufen wird. Dieses Script sourced das bereits erwähnte /usr/syno/etc.defaults/rc.ssh.subr erneut.

Konfigurationsdatei forcieren

Als mir das Debugging zu blöd wurde, habe ich mich entschieden, die Konfigurationsdatei ein für allemal in das eigentliche Startscript /usr/syno/etc.defaults/rc.ssh hartzukodieren:

...
$SSHD -f /etc/ssh/sshd_config
...

Debugging in syslog? Fehlanzeige

Wer denkt, dass einem folgende Zeilen beim Debugging in /etc/ssh/sshd_config weiterhelfen, liegt falsch:

...
SyslogFacility AUTH
LogLevel DEBUG
...

In /var/log/messages, der einzigen von zwei Log-Dateien in diesem Verzeichnis, welche bisher am heutigen Tag aktualisiert wurden, finden sich keine weiterführenden Infos, wieso sich der Benutzer mario nicht Schlüsseln einloggen darf.

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

Keine Kommentare | neuen Kommentar verfassen

Montag, 13. Januar 2014

Das PHP Error-Log von einem Cyon-Server täglich per E-Mail zusenden

Ein guter Web-Entwickler hält das PHP Error-Log seiner Web-Sites und -Applikationen stets im Auge. Ich persönlich habe mir zum Ziel gesetzt, dass nur ein leeres Log ein gutes Log ist. Dies bedeutet demzufolge, dass man auf Produktivsystemen sauberen Code ausliefert. Und sollten doch einmal Fehlermeldungen, Warnungen und Infos im PHP Error-Log auftauchen, gilt es diese zeitnah zu beheben.

Damit man eine Web-Präsenz, welche auf einem Cyon-Server mit SSH-Zugang läuft, überwachen kann, sind folgende Anpassungen nötig:

php.ini

Bei meinen Hostings befindet sich diese Konfigurationsdatei unter ~/etc/php_settings/default/php.ini. In dieser Datei sollten die folgenden Parameter gesetzt sein:

...
error_log = /home/%CYON-ACCOUNT%/var/log/php.err
...
error_reporting = E_ALL # Allenfalls auch & ~E_DEPRECATED
...

Dabei sollte man sicherstellen, dass das Verzeichnis /home/>benutzernamen>/var/log/ existiert und schreibbar ist.

mail-php-error-log.sh

Nachfolgendes Script sorgt dafür, dass der Inhalt der heutigen php.err per E-Mail an eine frei definierbare E-Mail-Adresse gesendet wird. Nach dem Versand wird die php.err kopiert und das Original danach gelöscht. Dem Dateinamen der Kopie wird dabei der aktuelle Tag des Jahres (1 bis 365) angehängt, womit wir eine Art automatisiertes logrotate durchführen:

#!/bin/sh

LOG="/home/%CYON-ACCOUNT%/var/log/php.err"

if [ ! -f "$LOG" ]
then
        echo "File '$LOG' not found"
        exit 1
fi

LINES=`cat "$LOG" | wc -l`

if [ $LINES -lt 1 ]
then
        exit 0
fi

#echo "Since log file is not empty ($LINES lines) I'm now posting its content to the webmaster"
cat "$LOG" | mail -s "php.err" logger@domain.tld
#echo "Would now be sending mail"

# Secret Sauce
DAYOFYEAR=$(date +%j)
cp "$LOG" "$LOG.$DAYOFYEAR"
rm "$LOG"

exit 0

Dieses Script habe ich in meinem Home-Folder abgelegt und mittels chmod 700 für meinen Benutzer ausführbar gemacht.

crontab

Schlussendlich richtet man sich noch einen Eintrag in crontab ein, damit das Script automatisiert einmal im Tag aufgerufen wird:

$ crontab -e

Der Inhalt dieser Datei lautet:

MAILTO="logger@domain.tld"
...
12 23 * * * /home/%CYON-ACCOUNT%/mail-php-error-log.sh

Tags: , , , , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Samstag, 14. Dezember 2013

syslog-ng motzt über nicht konforme Konfigurationssyntax

Bei den gelegentlichen apt-get dist-upgrades auf meinem Linux-Server motzt syslog-ng bei jedem Neustart des Services über eine inkompatible Syntax von /etc/syslog-ng.conf:

WARNING: Configuration file format is too old, syslog-ng is running in compatibility mode Please update it to use the syslog-ng 3.5 format at your time of convinience, compatibility mode can operate less efficiently in some cases. To upgrade the configuration, please review the warnings about incompatible changes printed by syslog-ng, and once completed change the @version header at the top of the configuration file.;

Wie löst man dieses Problem? Ich bin folgendermassen vorgegangen:

  1. Zuerst passe ich die Zeichenkette in /etc/syslog-ng.conf an. Anstelle der Version 3.3 trage ich dort frech wie ich bin einfach probehalber mal folgendes ein:

    @version: 3.5
    ...
  2. Als nächstes prüfe ich, dass syslog-ng mit den restlichen Angaben in der Konfigurationsdatei einverstanden ist — sprich in der Datei keine Syntax-Fehler vorhanden sind:

    # syslog-ng --syntax-only

    Wird hier keine Meldung gemacht, ist alles in bester Ordnung.

  3. Schlussendlich startet man syslog-ng neu:

    /etc/init.d/syslog-ng restart

Und gut is!

Tags: , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 17. November 2013

Finder-Eigenschaften von Dateien auf der Kommandozeile auslesen

Mit nachfolgendem bash-Script durchsuche ich einen Ordner mit über 700 Photos und gebe all diejenigen JPG-Dateien aus, welche im Finder die Farbe “Rot” zugewiesen haben:

#!/bin/sh

MDLS=`which mdls`
ATTRIBUTE="kMDItemFSFinderFlags" # Color
VALUE=12 # Red

for FILE in *.JPG
do
	RETVAL=$($MDLS -name "$ATTRIBUTE" "$FILE" | cut -d "=" -f 2)
	
	if [ $RETVAL -eq $VALUE ]
	then
		echo $FILE
	fi
done

exit 0

Alle zutreffenden Dateien kopiere ich mit folgendem Script in den Unterordner Highlighted (das obige Script habe ich unter filter-highlighted.sh abgelegt):

#!/bin/sh

FILES=`./filter-highlighted.sh`

for FILE in $FILES
do
	cp "$FILE" "Highlighted/"
done

exit 0

Tags: , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Samstag, 9. November 2013

E-Mail-Adressen aus einer Textdatei auslesen und mit imapfilter in einen Unterordner verschieben

Seit ich ein Smartphone besitze, verschiebe ich mittels dem alle 5 Minuten per cron-Job auf meinem privaten Server laufenden imapfilter unwichtige E-Mails in Unterordner, damit ich mich auf die wesentlichen Mails konzentrieren kann.

Der grösste Unterordner in meinem privaten E-Mail-Account heisst “_UNPERSOENLICH” und enthält all den Newsletter-Plunder, welchen man die Woche hindurch so zugeschickt erhält. Die imapfilter-Regel, welche die treffenden E-Mail-Absender herausfiltert und dorthin verschiebt, ist mittlerweile auf über 60 Zeilen (d.h. 60 Absenderadressen) angewachsen. In der imapfilter-Konfigurationsdatei sieht dies dann in etwa so aus:

...
messages = mbox.INBOX:contain_from('domain1.ch') +
           mbox.INBOX:contain_from('domain2.org') +
           mbox.INBOX:contain_from('user@domain3.com')
           ...
           mbox.INBOX:contain_from('userxy@domain112.com')
messages:move_messages(mbox['_UNPERSOENLICH'])
...

Heute habe ich mich dazu entschieden, diese E-Mail-Adressen aus der Konfigurationsdatei herauszulösen, in einer Textdatei zusammenzufassen (je eine E-Mail-Adresse pro Zeile) und dann imapfilter diese Textdatei einlesen zu lassen und die Absenderadressen in einer Schleife in meiner INBOX zu suchen und gegebenenfalls in den Unterordner zu verschieben.

Äusserst hilfreich war dabei die Hilfe, wie man Lua zu einem solchen Vorhaben bewegt (imapfilter setzt auf Lua auf): File Read In Lua?

Basierend auf dieser Antwort habe ich folgenden Code in meine imapfilter-Konfigurationsdatei aufgenommen:

...
function file_exists(file)
  local f = io.open(file, "rb")
  if f then f:close() end
  return f ~= nil
end

function lines_from(file)
  if not file_exists(file) then return {} end
  lines = {}
  for line in io.lines(file) do 
    lines[#lines + 1] = line
  end
  return lines
end
...
-- Unpersoenlich
local file = '../filters/private-unpersoenlich.txt'
local lines = lines_from(file)

for key,email in pairs(lines) do
--  print('line[' .. key .. ']', email)
  messages = mbox.INBOX:contain_from(email)
  messages:move_messages(mbox['_UNPERSOENLICH'])
end
...

Im Ordner oberhalb desjenigen Ordners, welcher die imapfilter-Konfigurationsdateien enthält (für jeden meiner Accounts existiert eine solche Konfigurationsdatei), gibt es nun einen Ordner filters, welcher momentan die Datei private-unpersoenlich.txt enthält.

Mit den obengenannten Funktionen und Konstrukten wird die Textdatei ausgelesen und in eine Lua-Tabelle (in anderen Programmiersprachen wohl als Array bezeichnet) gespeichert (lines_from(). Anschliessend gehe ich mit einem for-Loop durch die Tabelle, filtere den Absender (contain_from()) und verschiebe treffende E-Mail-Nachrichten in den Ordner “_UNPERSOENLICH” (move_messages(mbox['_UNPERSOENLICH'])).

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

1 Kommentar | neuen Kommentar verfassen