Start · Sprachen · PHP · Referenz · expect_popen

expect_popen

Funktion

Führt einen Befehl über die Bourne-Shell aus und öffnet einen PTY-Stream (Pseudo-Terminal) zum gestarteten Prozess.

Kategorie: misc

Signatur

expect_popen(string $command): resource|false

Beschreibung

expect_popen() ist Teil der PHP-Expect-Erweiterung und startet einen externen Befehl über die Bourne-Shell (/bin/sh -c). Im Unterschied zu popen(), das einen einfachen Pipe-Stream zurückgibt, öffnet expect_popen() ein Pseudo-Terminal (PTY). Dies ist entscheidend, wenn das aufgerufene Programm erkennen soll, ob es mit einem interaktiven Terminal verbunden ist – zum Beispiel bei SSH, FTP oder Passwort-Abfragen.

Der zurückgegebene Stream kann anschließend mit den Expect-Funktionen expect_expectl() oder expect_expectv() ausgewertet werden, um auf bestimmte Ausgaben des Prozesses zu warten und gezielt zu reagieren. Damit lassen sich Automatisierungsszenarien umsetzen, die interaktive Eingaben erfordern.

Typische Anwendungsfälle sind das automatisierte Anmelden an SSH-Servern, das Fernsteuern interaktiver CLI-Programme oder das Testen von Kommandozeilenprogrammen, die Benutzereingaben erwarten. Die Erweiterung muss separat installiert und in der php.ini aktiviert sein (extension=expect).

Wichtig: Der gestartete Prozess läuft unter dem Benutzer des PHP-Prozesses. Befehle sollten niemals unkontrolliert aus Benutzereingaben zusammengesetzt werden, um Command-Injection zu vermeiden.

Parameter

Name Typ Default Beschreibung
$command Pflicht string Der Befehl, der über die Bourne-Shell ausgeführt werden soll. Wird an /bin/sh -c übergeben. Niemals ungeprüfte Benutzereingaben einsetzen – stets escapeshellcmd() bzw. escapeshellarg() verwenden.

Rückgabewert

Typ
resource|false
Beschreibung
Gibt bei Erfolg eine Expect-Stream-Ressource zurück, die mit expect_expectl() oder expect_expectv() verwendet werden kann. Bei einem Fehler wird false zurückgegeben.

Beispiele

Automatisierte SSH-Anmeldung mit expect_popen

<?php
// Expect-Erweiterung muss installiert sein
$stream = expect_popen('ssh user@example.com');

if ($stream === false) {
    die('Konnte den Prozess nicht starten.');
}

// Auf Passwort-Aufforderung oder Host-Key-Bestätigung warten
switch (expect_expectl($stream, [
    ['password:', EXP_EXACT, 1],
    ['(yes/no)?', EXP_EXACT, 2],
])) {
    case 1:
        fwrite($stream, "geheimesPasswort\n");
        break;
    case 2:
        fwrite($stream, "yes\n");
        break;
    case EXP_TIMEOUT:
        die('Zeitüberschreitung beim Warten auf Prompt.');
    default:
        die('Unerwartete Ausgabe.');
}

fclose($stream);

Einfache Befehlsausführung und Ausgabe lesen

<?php
$command = escapeshellcmd('cat /etc/hostname');
$stream = expect_popen($command);

if ($stream === false) {
    die('Fehler beim Öffnen des Streams.');
}

// Auf Ausgabe warten
$result = expect_expectl($stream, [
    ['.+', EXP_REGEXP, 1],
], $match);

if ($result === 1) {
    echo 'Hostname: ' . $match[0] . PHP_EOL;
}

fclose($stream);
Hostname: mein-server

// Wichtig · Fallstricke

Sicherheit: Da expect_popen() den Befehl über die Shell ausführt, besteht ein erhöhtes Risiko für Command-Injection, wenn Benutzereingaben in den Befehl eingebaut werden. Immer escapeshellcmd() und escapeshellarg() verwenden und im Idealfall nur fest definierte Befehle nutzen.

Erweiterung erforderlich: Die Expect-Erweiterung ist kein Bestandteil der PHP-Standardinstallation. Sie basiert auf der systemseitigen libexpect-Bibliothek und muss über PECL (pecl install expect) installiert sowie in der php.ini aktiviert werden.

Verfügbarkeit: Die Erweiterung ist in der Regel nur unter Unix/Linux verfügbar, da PTYs unter Windows nicht unterstützt werden.

Ressourcen schließen: Den zurückgegebenen Stream nach Gebrauch immer mit fclose() schließen, um Prozesse und Dateideskriptoren nicht offen zu lassen.