Kategorien
Server Administration

Bash Script um Konsolen Befehle auf mehreren Servern auszuführen

Wenn man einen Cluster von Severn administrieren muss, hilft es sehr, wenn man Befehler „in einem Rutsch“ auf allen Mitgliedern des Clusters ausführen kann mit Hilfe eines einzigen Konsolen Befehls.

Wenn man z.B. den Befehl: apt-get update ausführen will auf 3 Servern, kann man folgendes Script benutzen (Dateiname ist „each“ und auf dem Master abzulegen):

#!/bin/bash
echo -e "\nServer1:"
ssh serverName1$*
echo -e "\nnServer2:"
ssh serverName2$*
echo -e "\nnServer3:"
ssh serverName3$*

Der Aufruf erfolgt folgender Maßen auf der Konsole:

each "apt-get update"

Das Skript verbindet sich dann per SSH auf die Server und führt auf jedem den Befehl apt-get update aus und zeigt das Ergebnis der Operation auf der Konsole an. Vorrausetzung ist, dass die Server ohne Passwort Zugriff aufeinander haben, was in einem Cluster der Fall sein sollte. Der Befehl sollte vom Master des Clusters aus ausgeführt werden.

Kategorien
MySQL

MySQL eigener Variablen in Query verwenden

Es ist sehr einfach möglich in MYSQL Variablen zu verwenden für MySQL Statements. Diese müssen definiert werden mit der SET Funktion und dem @-Prefix:

SET @a= 'a';

Und kann dann benutzt werden für die Dauer der DB-Session:

UPDATE my_table SET x = @a WHERE y = @a;

 

Kategorien
MySQL

History für MySQL Tabelle anlegen

Wenn man loggen will, wer wann und welche Änderungen an einer Tabelle „tabelle1“ gemacht hat, sollte man sich eine Tabelle namens „tabelle1_history“ und automatisch per MySQL Trigger auf Update und Delete Ereignisse reagieren:

Hinweis: __XYZ__ Platzhalter sind zu ersetzen

Trigger auf Update Aktionen

CREATE DEFINER=`__USER__`@`%` TRIGGER `__DB__`.`__TRIGGER_NAME_DEL__` BEFORE DELETE ON `__DB__`.`__TABLE__` FOR EACH ROW BEGIN
    insert into
        __DB__.__TABLE_HISTORY__
        (
        dataset_id,
        my_data1
        my_data2
        created_on
        created_by
        )

    VALUES (
        OLD.id,
        OLD.my_data1
        OLD.my_data2
        OLD.created_on,
        OLD.created_by
  );

Trigger auf Delete Aktionen

CREATE DEFINER=`__USER__`@`%` TRIGGER `__DB__`.`__TRIGGER_NAME_UPDATE__` BEFORE UPDATE ON `__DB__`.`__TABLE__` FOR EACH ROW BEGIN
        insert into
        __DB__.__TABLE_HISTORY__
        (
        dataset_id,
        my_data1
        my_data2
        created_on
        created_by
        )

    VALUES (
        OLD.id,
        OLD.my_data1
        OLD.my_data2
        OLD.created_on,
        OLD.created_by
  );
Kategorien
Apache Webserver

Apache Virtual Hosts einrichten unter MAC und Windows

Wenn man eine Seite lokal mit einem Werbserver wie Apache entwicklen will und die URL-Struktur Einfluss auf die Funktonsweise der Webseite hat, empfielt es sich Virtual Hosts einzurichten. Damit kann die Seite im Browser unter der späteren URL wie sebastianviereck.de erreichbar gemacht werden, obwohl Sie für andere noch nicht Online ist oder man die Domain noch nicht besitzt.

Normalerweise ruft man lokale Webseiten mit der URL wie:

http://localhost/sebastianviereck/

auf.

Wenn man stattdessen lieber die URL

http://sebastianviereck.local/

aurufen will, muss man einfach folgendes machen:

1. Die Datei

bei Windows xampp\apache\conf\extra\ httpd-vhosts.conf

bei MAC  /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf

ändern:

<Directory /xampp/htdocs    >   
    Order Allow,Deny   
    Allow from all 
</Directory>

NameVirtualHost *:80

<VirtualHost *:80>   
    DocumentRoot "/xampp/htdocs"
    ServerName localhost 
</VirtualHost> 

<VirtualHost *:80>   
    DocumentRoot "/xampp/htdocs/sebastianviereck"
    ServerName sebastianviereck.local
</VirtualHost>

2. Die Datei

bei Windows: C:\Windows\System32\drivers\etc\hosts

bei MAC /private/etc/hosts

ändern:

127.0.0.1  sebastianviereck.local
127.0.0.1   localhost   #damit localhost noch funktioniert, am Ende einfügen

3. Apache neu starten.

4. Im Browser erscheint dann bei der Eingabe von sebastianviereck.local die eigene lokale Webseite.

Kategorien
Diverses

Google Mail – unsichere Verbindung

Das google Mail nicht sicher ist und „unbefugte Dritte“ versuchen könnten Informationen zu stehlen, hat jeder schon vermutet, jetzt wird es auch von Google selber endlich zugegeben im Chrome:

google_mail_unsichere_verbindung

Kategorien
PHP PHP 7

PHP How to debug Segmentation Faults

Um Segementation Faults, die gerne in PHP7 zur Zeit auftreten zu bestimmen und zu analysieren, kann man folgender Weise vorgehen

1. Angabe des Speicherortes für die Coredumps

echo '/tmp/coredump_%e_%p' > /proc/sys/kernel/core_pattern

2. aktivieren der Coredumps in PHP-FPM

in der Datei: php-fpm.conf:

rlimit_core = unlimited     ; vorher: 0

3. PHP FPM restarten

service php-fpm restart

4. Analysieren der Coredumps mit gdb

Kategorien
PHP

SSH Verbindung mit PHP

Um eine SSH Verbindung mit PHP zu erstellen, gibt es mehrere Möglichkeiten:

Die saubere Lösung: Verbinden mit PHP-SSH2

Dazu muss die das Package php-ssh2 installiert werden, siehe php.net.

    $connection = ssh2_connect($host, $port);
    if(ssh2_auth_password($connection, $user, $password)){
        $stream = ssh2_exec($connection, $command);
        stream_set_blocking($stream, false);
        $stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
        $result = stream_get_contents($stream_out);
    }

Quick and dirty: Verbinden mit exec()

Einfach über die Console des Betriebsystems (sshpass sollte installiert werden, damit das Passwort mitangegeben werden kann).

$command = 'sshpass -p "'
    . $password
    . '" ssh -p '.$port.' '
    . $user. '@'. $host. ' "'
    . $sshCommand.'" ';
$result = exec($command);

Fingerprint umgehen bei wechselnden Ports

$command = 'sshpass -p "'
    . $password
    . '" ssh -p '.$port.' -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '    
    . $user. '@'. $host. ' "'
    . $sshCommand.'" ';
$result = exec($command);

In dem Beispiel wird mittels der Parameter

-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

die Fingerprint-Validierung umgangen, was man im Livebetrieb nicht machen sollten, bzw. man sollte sich den Fingerprint vorher auf der Console der Servers besorgen und dann benötigt man diese Parameter nicht.

 

Kategorien
PHP Server Administration

Nagios Plugins mit PHP schreiben

Nagios Plugins zum Monitoring von Servern und Funktionalitäten kann man in jeder verfügbaren Sprache schreiben. Die einzige Regel, an die man sich halten muss ist, dass der Return Code des Scriptes und der Response Text (enthält auch die Performance Daten) nach einem bestimmten Schema aufgebaut werden muss.

Als Hilfe kann man die Klasse NagiosPlugin benutzen, um Plugins zu schreiben:

abstract class NagiosPlugin {

    /**
     * @var boolean
     */
    protected $verbose = false;

    /**
     * setVerboseModeFromArgv
     * @see https://nagios-plugins.org/doc/guidelines.html#AEN41
     *
     * @param $argv
     * @return void
     */
    public function setVerboseModeFromArgv($argv) {
        if(in_array('-v', $argv)){
            $this->verbose = true;
        }
    }

    /**
     * addVerboseMessage
     *
     * @param $message
     * @return void
     */
    protected function displayVerboseMessage($message){
        if($this->verbose){
            echo $message.PHP_EOL;
        }
    }

    /**
     * endWithStatusOk
     * @see https://nagios-plugins.org/doc/guidelines.html#AEN200
     *
     * @param string $message
     * @param string $performanceData has format "nameOfData=value"
     * @return void
     */
    protected function endWithStatusOk($message, $performanceData){
        print "OK - $message".$this->addPerformaceData($performanceData);
        exit(0);
    }

    /**
     * endWithStatusWarning
     *
     * @param string $message
     * @param string $performanceData
     * @return void
     */
    protected function endWithStatusWarning($message, $performanceData){
        print "WARNING - $message".$this->addPerformaceData($performanceData);
        exit(1);
    }

    /**
     * endWithStatusCritical
     *
     * @param string $message
     * @param string $performanceData
     * @return void
     */
    protected function endWithStatusCritical($message, $performanceData){
        print "CRITICAL - $message".$this->addPerformaceData($performanceData);
        exit(2);
    }

    /**
     * endWithStatusUnknown
     *
     * @param string $message
     * @param string $performanceData
     * @return void
     */
    protected function endWithStatusUnknown($message, $performanceData){
        print "UNKNOWN - $message".$this->addPerformaceData($performanceData);
        exit(3);
    }

    /**
     * addPerformaceData
     *
     * @param string $performanceData
     * @return string
     */
    private function addPerformaceData($performanceData){
        $result = '';
        if(!empty($performanceData)){
            $result = ' | '.$performanceData;
        }
        return $result;
    }
}

 

Kategorien
MySQL

MySQL Update Deadlock InnoDB

Ein kniffeliges Problem ist letztens aufgetreten bei einer partitionierten MySQL Datenbank. Es kam immer wieder bei hoher Last zu Deadlock Meldungen seitens MySQL. Immer waren 2 Queries davon betroffen, die dieselbe Form hatten:

--Query1:
UPDATE myTable SET createdOn='2016-05-23 16:08:29', foo='y' WHERE id=1
--Query2:
UPDATE myTable SET createdOn='2016-05-23 16:08:29', foo='x' WHERE id=2

Im MySQL Error Log war ein solcher Eintrag zu finden:

mysql tables in use 1, locked 1
LOCK WAIT 106 lock struct(s), heap size 8400, 53 row lock(s)

Tip: Mit der Systemvariablen innodb_print_all_deadlocks (ab MySQL 5.5) kann man Deadlocks in InnoDB in das MySQL Error Log loggen und besser debuggen.

Eigentlich sollte es bei den beiden Queires nicht zu einem Deadlock kommen, da beide nur jeweils ein Row-Level Lock auf ihrer jeweilige Zeile haben sollten.

Dies ist auch der Fall, wenn es einen Index auf der Spalte id gibt. In diesem Fall allerdings war durch die Partitionierung der Primary (Unique) Index auf  2 Spalten gelegt worden (kombinierten Index): id und createdOn.

Dadurch, dass der Index auf beiden Soalten gelegt worden ist, kam es zu den dem Dealocks. Die Lösung war, das createdOn aus dem Update Statement zu entfernen, weil es an der Stelle auch keinen Sinn gemacht hat.

Kategorien
Redis

Redis Replikation Tipps

Beim Betrieb von Redis im Master/Slave Modus muss darauf geachtet werden, dass:

1. Master und Slave sind nicht immer auf demselben Stand

Redis uses asynchronous replication. Starting with Redis 2.8, however, slaves will periodically acknowledge the amount of data processed from the replication stream.

D.h. bestimmte Daten müssen vom Master abgefragt werden, wie z.B. Session Daten

2. Safety of replication when master has persistence turned off

In setups where Redis replication is used, it is strongly advised to have persistence turned on in the master, or when this is not possible, for example because of latency concerns, instances should be configured to avoid restarting automatically.

To better understand why masters with persistence turned off configured to auto restart are dangerous, check the following failure mode where data is wiped from the master and all its slaves:

We have a setup with node A acting as master, with persistence turned down, and nodes B and C replicating from node A.
A crashes, however it has some auto-restart system, that restarts the process. However since persistence is turned off, the node restarts with an empty data set.
Nodes B and C will replicate from A, which is empty, so they’ll effectively destroy their copy of the data.

When Redis Sentinel is used for high availability, also turning off persistence on the master, together with auto restart of the process, is dangerous. For example the master can restart fast enough for Sentinel to don’t detect a failure, so that the failure mode described above happens.

Every time data safety is important, and replication is used with master configured without persistence, auto restart of instances should be disabled.

d.h. die auto restart Funktion sollte für den Master deaktiviert werden, falls keine sofortige Persistierung auf der Festplatte aktiviert ist.

3. Master Ausfall

Wenn der Master ausfällt, sollte der Slave nach eine Karenzzeit sich zum Master erklären (z.B. nach 10 Minuten).