Sed – Manipulation von Textdateien

Sed ist ein Streaming Editor. Wer genaueres dazu wissen will, kann das auf Wikipedia nachlesen. Ich schreibe mir hier Zusammenstellungen auf, die mir merkenswert erscheinen.

Ersetzen in Dateien

Manchmal will einfach nur einen Wert an allen Stellen in einer Datei ersetzen:

sed -i 's/Alter Wert/Neuer Wert/g' /PfadZurDatei/Dateiname

Wer öfter mit vim arbeitet, dem wird die Suchen-/Ersetzen-Formation bekannt vorkommen. Weite Such-Ersetz-Möglichkeiten kann man hier nachlesen.

Will man z.B. etwas Anderes ersetzen, als das was man sucht, kann man das auch aufteilen:

sed '/Suchbegriff/ s/Alter Wert/Neuer Wert/' /PfadZurDatei/Dateiname

So werden in dem folgenden Beispiel alle Zeilen der NTP-Konfiguration auskommentiert, die auf den Debian NTP-Pool verweisen:

sed -i '/^server [0-3].debian.pool.ntp.org/ s/server/#server/g' /etc/ntp.conf

Konfiguration Apache Webserver

Mit dem Apache2 habe ich bisher mehrere Webserver aufgebaut. Dabei versuche ich unter Debian immer folgenden Aufbau zu nutzen.

VirtualHost-Konfigurationen

/etc/apache/sites-available/<vhostName>

So kann man diese einfach per „a2ensite“ und „a2dissite“ aktivieren und deaktivieren.

<VirtualHost *:80>
       ServerAdmin webmaster@example.com
       ServerName sub.domain.tld
       
       DocumentRoot /srv/www/vhosts/<vhostName>/htdocs/
       
       ErrorLog /var/log/apache2/<vhostName>/error.log
       LogLevel warn
       CustomLog /var/log/apache2/<vhostName>/access.log combined
       
       ErrorDocument 404 /error/404.html
       ErrorDocument 403 /error/403.html
       ErrorDocument 401 /error/401.html
       
       <Directory /srv/www/vhosts/<vhostName>/htdocs/>
               Options -Indexes FollowSymLinks
               AllowOverride None
               Order allow,deny
               allow from all
       </Directory>
       
       Alias /error /srv/www/vhosts/<vhostName>/ErrorDocuments
       <Directory /srv/www/vhosts/<vhostName>/ErrorDocuments/>
               Options None
               AllowOverride None
               Order allow,deny
               allow from all
       </Directory>
       
</VirtualHost>

Virtual Host Container

Ich nutze einen separaten Ordner als Container für alle Dateien, die diese Webseite betreffen …

/srv/www/vhosts/<vhostName>
/srv/www/vhosts/<vhostName>

… mit folgender Unterstruktur

drwxr-xr-x   2  root            root           4,0K 30. Apr 15:51 config
drwxr-xr-x   2  root            root           4,0K 30. Apr 15:51 ErrorDocuments
drwxr-xr-x   2  root            root           4,0K 30. Apr 15:51 htaccess
drwxr-xr-x   15 www-data        www-data       4,0K  2. Mai 12:27 htdocs

Der Ordner ErrorDocuments kann eigene Fehlerseiten enthalten, die so auch bei geschütztem Hauptbereich durch einen Alias getrennt freigegeben werden können (s.o.). Der Ordner htaccess enthält evtl. vorhandene Zutritts- oder Umschreibungsdateien, die so wieder separat vom Hauptbereich geschützt werden können. Der Ordner htdocs enthält den DocumentRoot des Virtual Hosts. Der Ordner config enthält zwei Dateien. Einmal lr-<vhostname> mit einer Konfiguration für den logrotate-Dienst und braucht so nur in das Verzeichnis /etc/logrotate.d/verlinkt werden. Und zum zweiten die Apache-Konfiguration a2-<vhostname>. So kann auch diese Datei einfach in das Verzeichnis/etc/apache2/sites-available verlinkt werden.

Log-Dateien

Die Logdateien sollten abhängig vom Betriebssystem in der dafür vorgesehenen Partion abgelegt werden. Durch diese Abtrennung kann verhindert werden, dass eine vollgelaufene Log-Partition das gesamte System zum Absturz bringt. Bei Debian lege ich die Webserver-Logs wie folgt ab:

/var/log/apache/<vhostName>
/var/log/apache/<vhostName>/old

Backup der vHosts

Backups sollten auf jeden Fall automatisch laufen, da einem sonst gerade die Daten fehlen, die man gerade benötigt.

Für die einzelnen vHost des Apache realisiere ich das per Script, das mir die gepackten Archive unter

/var/backups/www

ablegt. Es werden dabei automatisch für jeden einzelnen vHost-Ordner ein Backup-Ordner angelegt und dort jeweils in tägliches und wöchentliches Backup unterschieden. Da ich die wöchentlichen Backups aufhebe, verzichte auf monatliche Backups.

#!/bin/sh
# Angaben zu Quelle und Ziel
src=/srv/www/vhosts
dest=/var/backups/www
# Unterordner mit Archivnamen im Zielverz. erzeugen (0/1)?
sd=1
### Hilfsvariablen ###
# Wochentag
wd=$(date +"%w")
# Kalenderwoche
kw=$(date +"%W")
# Monat
mo=$(date +"%m")
# Jahr
year=$(date +"%Y")
# Datum
d=$(date +"%Y%m%d")
 
# Pruefen, ob Quellverzeichnis vorhanden ist...
if [ ! -e $src ]; then
  /bin/echo "Quellverzeichnis $src nicht vorhanden oder kein Zugriff"
  exit 0
fi
 
# Pruefen, ob Zielverzeichnis vorhanden ist...
# ... und wenn nicht, anlegen
if [ ! -e $dest ]; then /bin/mkdir -p $dest; fi
 
# Ins Quellverzeichnis wechseln, damit tar keine
# fuehrenden / entfernen muss...
# ... und dadurch keine Ausgaben bei Cron-Jobs entstehen
cd $src
 
# Alle vHost-Ordner einzeln packen
for i in $(/bin/ls); do
  # Alte Datei loeschen
  if [ -e $dest/$wd-$i*.tar.gz ]; then /bin/rm $dest/$wd-$i*.tar.gz; fi
  if [ -e $dest/$i/taeglich/$wd-$i*.tar.gz ]; then /bin/rm $dest/$i/taeglich/$wd-$i*.tar.gz; fi
  # Neue Datei erstellen
  if [ $sd == 1 ]; then
    if [ ! -e $dest/$i/taeglich ]; then /bin/mkdir -p $dest/$i/taeglich; fi
    /bin/tar -czf "$dest/$i/taeglich/$wd-$i-$d.tar.gz" $i
  else
    /bin/tar -czf "$dest/$wd-$i-$d.tar.gz" $i
  fi
  # Wochen-Datei kopieren
  if [ $wd == 1 ]; then
    if [ ! -e $dest/$i/woechentlich ]; then /bin/mkdir -p $dest/$i/woechentlich; fi
     /bin/cp "$dest/$i/taeglich/$wd-$i-$d.tar.gz" "$dest/$i/woechentlich/$year-$kw-$i-$d.tar.gz"
  fi
done

Absicherung des Apache-Servers

Ein Apache Webserver ist sehr gut für die Entwicklung geeignet, weil er viele Informationen ausgeben, die eine Fehlerbehebung und Entwicklung unterstützen. Diese Informationen sollten auf Produktivsystem aber nicht für die Öffentlichkeit verfügbar sein. Daher sollte man noch ein paar Sicherheits-Einstellungen für den Webserver vornehmen.

Single Sign On und Kerberos auf Debian

Wer jetzt noch seinen Apache Webserver auf Debian im Windows-Intranet mit SSO zu einem 2008 R2 AD Domain-Controller einrichten will, findet bei Stefan Macke den Beitrag „Single Sign On with Kerberos using Debian and Windows Server 2008 R2

Datetime-Wert zerlegen

Folgende Beschreibung hab ich im entwickler-forum.de gefunden.

Über die DATEPART-Funktion kann eine SELECT-Abfrage nur bestimmte Bestandteile zurückliefern.

 DECLARE @mydatetime DATETIME
 DECLARE @myms INT
 DECLARE @myss INT
 DECLARE @mymi INT
 DECLARE @myhh INT
 DECLARE @mydd INT
 DECLARE @mymm INT
 DECLARE @myyyyy INT
 
 SET @mydatetime=getdate()
 SET @myms = DATEPART(ms,@mydatetime)
 SET @myss = DATEPART(ss,@mydatetime)
 SET @mymi = DATEPART(mi,@mydatetime)
 SET @myhh = DATEPART(hh,@mydatetime)
 SET @mydd = DATEPART(dd, @mydatetime)
 SET @mymm=DATEPART(mm,@mydatetime)
 SET @myyyyy = DATEPART(yyyy, @mydatetime)
 
 SELECT @myyyyy AS 'Year', @mymm AS 'Month', @mydd AS 'Day of month',
        @myhh AS 'Hour', @mymi AS 'Minute', @myss AS 'Second',
        @myms AS 'Millisecond'

 

Veröffentlicht in MSSQL

Rolle und Status einer Spiegel-Datenbank

Mit dem folgenden Snippet kann man sich den Status einer gespiegelten MS-SQL-Datenbank und die Rolle des aktuellen Servers anzeigen lassen:

-- Die Abfrage ist für die Serverrolle public möglich.
SELECT mirroring_role_desc AS 'Rolle', mirroring_state_desc AS 'Status'
 FROM sys.database_mirroring
 WHERE mirroring_guid IS NOT NULL
 AND database_id=(
   SELECT dbid FROM master.dbo.sysdatabases WHERE name = '<Datenbankname>'
 )

 

 

Veröffentlicht in MSSQL

Doppelte Zeilen löschen

Sub doppelteLöschen()
   Dim LastC As Long, x As Long
   LastC = Range("a65536").End(xlUp).Row
   For x = LastC To 1 Step -1
       If WorksheetFunction.CountIf(Range("a1:a" & x), Cells(x, 1)) > 1 Then
           Cells(x, 1).EntireRow.Delete
       End If
   Next
End Sub

Die For … Next-Schleife fängt bei der letzten beschriebenen Zelle an. Das wird erreicht durch:

LastC = Range("a65536").End(xlUp).Row

Quelle

Veröffentlicht in Excel
mit getaggt

SQL Suchen/Ersetzen

Bei manchen Übernahmen von Texten in eine MySQL-Datenbank mit UTF-8 passiert es, dass die Umlaute nicht korrekt übernommen werden. Durch ein einfaches Suchen/Ersetzen über die entsprechende Spalte ist das aber schnell behoben.

UPDATE <tabelle>
      SET <feld>=replace(replace(replace(replace(replace(replace(replace(replace(<feld>,'ß','ß'),'ä','ä'),'ü','ü'),'ö','ö'),'Ä','Ä'),'Ãœ','Ü'),'„','"'),'“','"')
WHERE <feld> LIKE '%ß%' OR <feld> LIKE '%ä%' OR <feld> LIKE '%ü%' OR <feld> LIKE '%ö%' OR <feld> LIKE '%Ä%' OR <feld> LIKE '%Ü%' OR <feld> LIKE '%„%' OR <feld> LIKE '%“%'

 

Veröffentlicht in MySQL

bind Logging

Um die Konfiguration sauber trennen zu können, habe ich die Logging-Konfiguration in eine separate Datei aufgeteilt und diese in der named.conf eingebunden.

...
// If you are just adding zones, please do that in /etc/bind/named.conf.local

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.log";

// prime the server with knowledge of the root servers
...

 

logging {
    channel bind9log {
        file "/var/log/named/bind9.log" versions 3 size 10m;
        // syslog info;
        // severity debug;
        severity dynamic;
        print-time yes;
        print-severity yes;
        print-category yes;
    };
    channel security {
        file "/var/log/named/security.log" versions 2 size 5m;
        // syslog warn;
        // severity warn;
        severity dynamic;
        print-time yes;
        print-severity yes;
        print-category yes;
    };
    category resolver {bind9log;};
    category default {bind9log;};
    category queries {bind9log;};
    category client {bind9log;};
    category config {bind9log;};
    category notify {bind9log;};
    category unmatched {bind9log;};
    category dispatch {bind9log;};
    category dnssec {bind9log;};
    category database {bind9log;};
    category security {security;};
    category lame-servers {null;};
};

Zusätzlich muss das oben angegebene Verzeichnis /var/log/named noch angelegt werden:

mkdir /var/log/named

Danach einen Neustand von bind:

/etc/init.d/bind9 restart

und alles ist erledigt, wie ein ein ls zeigt:

DNS1:/etc/bind# ls -alh /var/log/named/
insgesamt 132K
-rw-r--r-- 1 bind bind 126K 24. Nov 16:08 bind9.log
-rw-r--r-- 1 bind bind 0   24. Nov 15:41 security.log

bind RNDC-Administration

Wurde der DNS-Server für automatisch Aktualisierungen durch den DHCP-Server eingerichtet, können die dynamischen Zonnen nicht einfach aktualisiert und neu eingelesen werden. Zuerst muss die Dynamik mit der RNDC-Administration „eingefroren“ werden:

rndc freeze <example.com>

Dann die die Domänen-DB-Datei und die dazugehörige PTR-Datei mit dem Editor der Wahl bearbeiten und !!! die Seriennummer hochzählen !!! Danach kann die Zone neu geladen und wieder „aufgetaut“ werden:

rndc reload <example.com>
rndc thaw <example.com>

DNS-Forwarder pro Zone einrichten

bind9 ist ja nach der Standard-Installation ein Proxy-DNS, der sich sein Weiterleitungsserver aus der/etc/resolv.conf lädt. Setzt man bind aber auf einem Gateway ein, so kann es ja vorkommen, dass verschiedene Zonen von verschiedenen Servern abgefragt werden sollen. Nichts leichter als das.

Zuerst muss eine Zonenkonfiguration angelegt werden. Je nach Anzahl der Zonen kann man diese in eine Datei schreiben oder ein Zone pro Datei. Da der Rahmen bei mir meist überschaubar ist, schreibe ich eine Datei pro Zone und kann diese dann bei Bedarf einzeln aktivieren und deaktivieren.

// Weiterleitung fuer domain1.tld
zone "domain1.tld" in {
type forward;
forwarders { 192.168.178.1; };
};
// Weiterleitung fuer domain2.tld
zone "domain2.tld" in {
type forward;
forwarders { 10.50.100.1; 10.50.100.2; 10.70.70.3; };
};

 

Wie zu sehen ist, kann man auch mehrere Weiterleitungsserver eintragen. Alle durch ein Semikolon getrennt.

Bis jetzt verschwenden die Dateien nur Platz auf der Festplatte, weil bind sie nicht kennt. Sie müssen also in der Hauptkonfiguration eingetragen werden. Da bei der Installation bereits eine lokale Version der named.conf angelegt wurde, sollte diese dafür genutzt werden.

Datei: /etc/bind/named.conf.local

//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
include "/etc/bind/zones.domain1.tld";
include "/etc/bind/zones.domain2.tld";

// Vertrauenswürde Clients (Eigenes LAN)
...

Zum Schluss noch den bind neu starten, damit die Konfigurationen eingelesen werden.

Ab jetzt werden die DNS-Einträge für die explizit konfigurierten Domains bei den expliziten DNS-Servern abgefragt. Alle anderen werden wie bisher bei den Servern aus der /etc/resolv.conf abgefragt.

infoJetzt kann man den eigenen Server (127.0.0.1) in der /etc/resolv.conf an die erste Stelle schreiben, damit die expliziten Konfigurationen mit benutzt werden.

warnungWenn, wie oben angedeutet Acess Listen für den Zugriff definiert sind, muss man prüfen, ob der localhost hier bisher mit bedacht worden ist.