Lerne Coding
Einfache Server-Automatisierung in PHP
10.10.2020

Server-Automatisierung mit PHP

Inhaltsverzeichnis
[[TABLE OF CONTENTS]]
access_timeGeschätzte Lesezeit ca. Minuten

Manchmal gibt es Aufgaben, für die ein Webseitenaufruf nicht geeignet ist, weil dies entweder zu unsicher ist oder die Verarbeitung länger dauert. Um dennoch beispielsweise Code einer Webseite wiederverwenden zu können und nicht alles in Java, Python oder C++ neu programmieren zu müssen, kann man PHP auch im Terminal ausführen. Entweder, indem man php dateiname.php manuell ausführt oder indem man dem System sagt, es solle die Datei bitte jeden Tag um die selbe Zeit X ausführen. Dabei gibt es kleine Kniffe und Einzelheiten, die sich zur Browserversion unterscheiden. Diese möchte ich dir nun nach und nach erklären.

Cronjobs

Was sind Cronjobs? Cronjobs sind Events, welche von deinem Betriebssystem zeitabhängig in einem eigenen Thread ausgeführt werden. So kannst du z.B. sagen: "Sende doch bitte um 3 Uhr nachts, wenn weniger Traffic auf deiner Webseite ist, Emails an die Kunden, mit der Mitteilung, dass es jetzt 20% Rabatt gibt". Somit musst du dein Programm nicht in der Dauerschleife laufen lassen und sparst Performance im Leerlauf.

Wie installiere ich Cronjobs?

Unter Linux gibt es den Befehl crontab -e. Wenn du diesen Befehl zum ersten Mal ausführst, musst du deinen Lieblingseditor auswählen. Ich empfehle dir Nano da es ein kleiner, moderner Texteditor ist. Fühlst du dich mit VI(M) wohler und dessen historischen Eigenheiten, kannst du diesen aber natürlich auch verwenden. Nun öffnet sich eine Datei. Scrolle bei dieser bis ans Ende und füge für jeden Cronjob eine neue Zeile ein. Inaktive Zeilen fangen mit einem # an. Der restliche Inhalt der Zeile wird dann nicht mehr ausgeführt.

Einen neuen Cronjob anlegen

Nachdem du nun die Cronjob-Datei geöffnet hast, musst du unter den Kommentaren deinen Befehl eingeben. Dabei gibt es ein ganz bestimmtes Format:

  1. Minute (0-59/*)
  2. Stunde (0-23/*)
  3. Tag (1-31/*)
  4. Monat (1-12/*)
  5. Wochentag (1-7/*)
  6. Befehl

Sternchen bedeutet einfach z.B. jede Minute oder jeden Tag. Ich würde dir empfehlen, beim Ausführen des Kommandos ganze Dateipfade anzugeben. Hier ein Beispiel: Ich möchte täglich die Paketquellen um 3:00 Uhr nachts updaten:

0 3 * * * apt update
// 0 Minuten, 3 Uhr, jeden Tag, jeden Monat, jeden Wochentag -> apt update

Um jetzt eine PHP-Datei auszuführen, die jeden Mittwoch um 12 Uhr eine Datei ausführt um den neusten Newsletter per Mail zu verschicken, schreiben wir also Folgendes:

0 12 * * 3 php /full/path/to/file/file.php
Achtung

Systemupdates sollten manuell ausgeführt werden, da es passieren könnte, dass Abhängigkeiten geupdatet werden, mit denen dein Programm nicht mehr kompatibel ist. Wenn du dein System unbedingt updaten möchtest, dann beschränke dich auf die Sicherheitsupdates!

Datei speichern und Nano verlassen

Wenn du mit dem Bearbeiten fertig bist, kannst du entweder STRG + X zum Verlassen drücken oder zum Zwischenspeichern STRG + S. Wenn du gerade gespeichert hast, kannst du Nano verlassen, ohne dass er dich fragt, ob du die Datei wirklich speichern möchtest. Möchtest du den Editor Nano näher kennen lernen, schau dir doch das Video von Go2Prepaid dazu an, da habe ich mitgewirkt und ausführlich Tipps und Tricks rund um den Editor erklärt.

#60 Einfach Erklärt: Nano Shortcuts

Nutzer benachrichtigen

Wenn man einen Newsletter versenden möchte oder anderweitig Informationen nach außen tragen muss, dann ist es von Vorteil, Emails und SMS mit PHP versenden zu können. Deshalb gehe ich hier noch einmal kurz auf diesen Aspekt ein.

Email versenden

Funktioniert genau wie im Web! Falls du dennoch Probleme dabei haben solltest, kannst du dir meinen Artikel zum PHPMailer durchlesen oder dich im HelloCoding Discord Forum melden.

SMS versenden

Bei ganz dringenden Events wie Serverausfällen kann es sein, dass du dich selbst per SMS benachrichtigen möchtest, unabhängig davon, ob du gerade im Internet bist oder nicht. Ich bevorzuge dazu den Anbieter Lox24, den man mit einer einfachen Anfrage dazu beauftragen kann eine SMS zu versenden. Lox wird zwar hauptsächlich von Firmen verwenden, du kannst es aber auch privat nutzen. Du musst lediglich 40€ aufladen, was für einige SMS reichen sollte. Ein Beispiel für den Umgang mit der API findest du auf meinem GitHub-Gist Account. Falls du dir darüber noch einmal einen ausführlicheren Artikel wünschst, schreibe mir das gerne als Kommentar oder im Discord Server.

Systemeingaben

Wenn du dein Programm dynamisch aufrufen möchtest, ähnlich bei GET bei Webseiten, dann hast du folgende Möglichkeiten auf Werte zuzugreifen:

Als Texteingabe

Wenn du dein Programm nicht mit einem Cronjob sondern persönlich ausführst und dem Script auch noch die ein oder andere Information mitgeben möchtest, musst du Eingaben verarbeiten können. In PHP gibt es dafür die readline Funktion, welche so lange mit der weiteren Ausführung deines Threads wartet, bis du etwas eingegeben hast.

readline ([ string $prompt = NULL ] ) : string
echo "insert something...";
$input = readline("> ");
echo "Einagabe: ".$input;

Als Parameter beim Aufruf

Wer schon einmal mit C, C++, Java oder vergleichbaren Sprachen gearbeitet oder einmal Linux verwendet hat, dem ist sicher aufgefallen, dass man in der Kommandozeile Programme mit Parametern aufrufen kann, so wie ls -la. Doch wie kann man so etwas in PHP realisieren?

Wenn das Programm in der Shell aufgerufen wird, sind die Variablen argv und argc definiert. Argc gibt die Menge der Parameter an und Argv die jeweiligen Werte als Array. Die Parameter werden anhand der Leerzeichen getrennt. Es gibt Frameworks wie bspw. die C++ Library argparser, wo man dann einfach nur die möglichen Parameter angibt, ob oder wie sie beim Aufruf angegeben wurden. In PHP hat der Nutzer hfcorriez dazu ein kleines Composer Package geschrieben.

Erkenne das Betriebssystem

Unter den Betriebssystemen gibt es manchmal kleine Unterschiede, welche abgefangen werden müssen. Hier mal eine kleine Funktion zur Erkennung, auf welchem Betriebssystem du dich gerade befindest.

/*
  OS_UNKNOWN = 1;
  OS_WIN = 2;
  OS_LINUX = 3;
  OS_OSX = 4;
*/

function getOS() {
  switch (true) {
      case stristr(PHP_OS, 'DAR'):   return 4;
      case stristr(PHP_OS, 'WIN'):   return 2;
      case stristr(PHP_OS, 'LINUX'): return 3;
      default : return 1;
  }
}

Quelle: Stackoverflow

Erkenne deine PHP-Version

Wenn du die aktuelle Version deines PHP-Systems brauchst, kannst du dir diese mit echo phpversion() ausgeben lassen. Bei dieser Funktion kannst du auch einen String übergeben, falls du prüfen möchtest, in welcher Version z.B. deine cURL-Extension vorhanden ist.

Möchtest du jetzt aber angeben, du unterstützt nur PHP ab Version 7, hilft dir die Funktion version_compare(). Mit ihr kann entweder ermittelt werden, ob eine Version höher, tiefer oder gleich ist. Dazu bietet die Funktion einmal eine Möglichkeit, bei der ein Integer zurückgegeben wird, der nur -1 0 oder +1 sein kann. Du kannst aber auch den Operator angeben und bekommst ein Boolean zurück.

version_compare ( string $version1 , string $version2 ) : int
version_compare ( string $version1 , string $version2 , string $operator ) : bool
echo "Deine PHP Version ist zur Zeit die: ".phpversion();
if (version_compare(phpversion(), 7.0) < 0) {
    echo "[ ERROR ]";   
    echo "Deine PHP Version ist zu alt und wird nicht mehr unterstützt";
} else if (version_compare(phpversion(), 8.0) >= 0) {
    echo "[ WARNUNG ]";
    echo "Dieses Programm ist für PHP 8 noch nicht optimiert und kann zu Problemen führen";
}

Lokale Systemvariablen

Je nach System kann die globale Servervariable gewisse Informationen über das System herausfinden. Welche das bei deinem Hostsystem sind, kannst du gerne mit print_r(array_keys($_SERVER)); nachschauen. Hier ist ein Beispiel, was du so von einer Windows- und einer Linux Mint-Hostmaschine erwarten kannst. Bitte verlasse dich aber nicht auf diese Werte und prüfe immer, ob diese gesetzt wurden oder gültig sind. Ich habe das Ergebnis mal etwas gekürzt, damit der Artikel nicht zu lang wird.

// Windows
php > print_r(array_keys($_SERVER));
Array
(
    [7] => COMPUTERNAME
    [14] => HOMEPATH
    [22] => OS
    [29] => ProgramData
    [30] => ProgramFiles
    [31] => ProgramFiles(x86)
    [32] => ProgramW6432
    [36] => python
    [44] => USERNAME
    [48] => PHP_SELF
    [49] => SCRIPT_NAME
    [50] => SCRIPT_FILENAME
    [52] => DOCUMENT_ROOT
    [53] => REQUEST_TIME_FLOAT
    [54] => REQUEST_TIME
)

// linux
php > print_r(array_keys($_SERVER));
Array
(
    [6] => LANG
    [17] => USER
    [18] => DESKTOP_SESSION
    [23] => HOME
    [32] => GTK_MODULES
    [35] => SHELL
    [43] => LANGUAGE
    [47] => LOGNAME
    [53] => PATH
    [55] => CINNAMON_VERSION
    [57] => SESSION_MANAGER
    [59] => LC_TIME
    [61] => PHP_SELF
    [62] => SCRIPT_NAME
    [63] => SCRIPT_FILENAME
    [64] => PATH_TRANSLATED
    [65] => DOCUMENT_ROOT
)

Programme ausführen mit PHP

Die Funktionen, die dafür gebraucht werden, sind von PHP standardmäßig deaktiviert, da man diese Funktionen sehr leicht missbrauchen kann, indem man Befehle mit dynamischen Werten gefährlich abändert. Möchtest du ein Script schreiben, welches serverunabhängig laufen soll, prüfe erst, ob die Funktion überhaupt aktiviert wurde. Dazu verwende ich zuerst die Funktion function_exists und führe anschließend eine harmlose Terminaleingabe durch:

if (function_exists('shell_exec') and !empty(shell_exec('echo foobar'))) {
    die("shell_exec ist aktiviert");
} else {
    die("shell_exec ist deaktiviert");
}

Ein externes Programm ausführen

Mit der Funktion exec können externe Programme und Befehle ausgeführt werden, sodass sich dessen Output wie folgt ändert:

exec ( string $command [, array &$output [, int &$return_var ]] ) : string
echo exec('whoami');
echo exec('whoami', $outputperline, $successfull)."\n";
if($successfull == 1) {
    // done
} else {
    // error
    foreach($outputperline as $zeile => $content) {
        echo $content."\n";
    }
}

// output
uvulpos
uvulpos

Den Wert eines dynamisch generierten Befehls eingeben und absichern

Mit escapeshellcmd kann verhindert werden das Schadcode ins System eingefügt wird und Sicherheitslücken verursacht.

escapeshellcmd ( string $command ) : string
$command = './configure '.$user_optionen_via_GET_bspw;
$escaped_command = escapeshellcmd($command);
exec($escaped_command);

Datenbankzugriff

Es ist in dem Fall wichtig, das die Extension für Mysqli oder PDO aktiviert sind. Ansonsten kannst du diese ganz normal verwenden.

Datenbank-Backups erstellen

Bei MySQL gibt es das Programm mysqldump, welches ich problemlos als Kommando in meiner Shell ausführen kann (Linux). Wenn du bspw. Xampp unter Windows verwendest, ist das Tool auch installiert; jedoch musst du dann den kompletten Dateipfad angeben. Das Programm befindet sich meistens in C:\Windows\xampp\mysql\bin\mysqldump.exe. Je nach dem, wo du Xampp installiert hast, kann es sein, das dieser Dateipfad abweicht. Falls der Pfad nicht copy paste funktionieren sollte, dann prüfe einmal, ob die Schreibweise passt. Ich habe den Pfad kopiert, aber noch nicht getestet. Unter Linux kann ich mir nun mit "man mysqldump" eine Anleitung anzeigen lassen, welche Parameter vorhanden sind.

Nun ist es eigentlich egal, ob du diesen Prozess mit PHP oder bash ausführst, weil wir das Programm mit Parameter aufrufen und dieses uns automatisch eine Datei erstellt. Wie man eine Datei in PHP aufruft, habe ich dir oben erklärt.

$command = "mysqldump --user=\"root\" --password=\"123\" --databases mysql > /path/to/file.sql";
exec($command);

Diese Methode hat aber das entscheidende Problem, dass, wenn auf dem Server mehrere Leute arbeiten, das Passwort in Klartext auslesbar ist. Diese Methode sollte eher auf privaten Servern verwendet werden oder, falls du der einzige Nutzer des Servers bist. Ansonsten würde ich dir eher zur zweiten Methode raten:

MySQL-Datenbank mit einer PHP-Funktion backuppen

Der Entwickler ttodua hat dazu eine kleine PHP-Funktion geschrieben, welche er auf GitHub hochgeladen hat. Diese meldet sich via mysql in der Datenbank ein und generiert eine .sql-File, welche alle Tabellen und Daten der Datenbank besitzt und entweder in der gleichen Datenbank oder in anderen mysql-Datenbankinstallationen wieder importiert wird. Falls du aber lieber eine Datei hättest, dann schau dir meinen modifizierten Gist an. Dieser erstellt dir eine Datei, sofern du einen Dateipfad angibst. In allen Fällen gibt er dir auch den Inhalt als String zurück, falls du diesen anderweitig noch verwenden möchtest. Ich gehe davon aus, dass diese Funktion nicht weiter maintained wird, also könnte es durchaus irgendwann in der Zukunft passieren, dass diese Funktion plötzlich nicht mehr funktioniert. MySQL Dump sollte aber keine Fehler aufweisen und in der Zukunft weiterhin unterstützt werden.

Fazit

Abschließend möchte ich dir noch Beispiele für die Serverautomatisierung oder Kommandozeilenprogrammierung mit PHP an die Hand geben:

  • Serverausfälle tracken
  • Wichtiges Programm ist abgestürzt oder läuft auf Fehler
  • Newsletter rausschicken
  • Rechnungen rausschicken
  • Automatisierter Rechnungsdruck für die Buchhaltung
  • Laufzeit beendeter Mitgliedschaften beenden
  • MySQL-Backup speichern und das älteste löschen
  • Laufzeit beendeter Mitgliedschaften beenden
Bildquelle - Vielen Dank an die Ersteller:innen für dieses Bild
Kommentare zum Artikel

Es sind noch keine Kommentare vorhanden? Sei der/die Erste und verfasse einen Kommentar zum Artikel "Einfache Server-Automatisierung in PHP "!

Kommentar schreiben

Verwante Beiträge
close