Signatur
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
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);
// 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.