schneerunzel
Goto Top

PythonScript aus PHP ausführen und Ausgabe ausgeben

Moin zusammen,

ich habe ein Webanwendung auf PHP Basis. Mit dieser Anwendung sollen Dokumente zusammengestellt und Aufbereitet werden. Diese Aufbereitung existiert in Python.
Jetzt möchte ich gerne aus der PHP Anwendung heraus die Python Scripte zur Verarbeitung aufrufen. Dabei soll aber nicht nur das Aufrufen im Hintergrund getriggert werden, sondern es soll die Ausgabe des Python Scriptes während der Laufzeit ausgegeben werden. Die Python Scripte brauchen in der Regel immer einige Minuten, in denen Sie aber protokollieren was gerade passiert. Diese Ausgabe möchte ich dem Nutzer im Browser gerne "live zeigen".

Hat jemand einen Tipp für mich, wie so etwas funktionieren kann?

Vielen Dank vorab.

Content-Key: 1332856339

Url: https://administrator.de/contentid/1332856339

Printed on: April 26, 2024 at 16:04 o'clock

Mitglied: 149569
149569 Oct 01, 2021 at 17:00:51 (UTC)
Goto Top
Member: colinardo
Solution colinardo Oct 02, 2021 updated at 12:11:36 (UTC)
Goto Top
Servus @schneerunzel,
das ist kein Problem mit etwas Ajax gewürzt lässt sich das verwirklichen. Habe dir mal ein ganz primitives "Single-Page" Beispiel dazu gebaut, im Normalfall macht man daraus zwei separate Seiten( eine für das Frontend und eine für das Backend das die Daten an das Frontend liefert). Ich möchte explizit darauf hinweisen das das so niemals live gehen sollte da hier jegliche Arten von Kommandos ausgeführt werden können für die der ausführende Prozess-User des Webservers Rechte besitzt. Das kannst du ja dann selbst auf deine Bedürfnisse einschränken was wo ausgeführt werden darf. Habe es so umgesetzt damit man selbst erst mal ein paar Kommandos ausprobieren kann ohne erst viel Variablen anpassen zu müssen.

Wichtig: Damit python Skripte die Live-Ausgabe funktioniert muss man die Ausgabe der Skripte auf unbuffered einstellen, für Shell-Skripte ist das nicht nötig die funktionieren so. Bei python erledigt das der Kommandozeilenparameter -u.
Deine Python-Skripte solltest du also folgendermaßen in der Textbox der HTML-Seite starten
python -u /pfad/zum/script.py
Ebenso muss man beachten das der User unter dem der Webserver läuft auch Lese- und Execute Rechte auf den entsprechenden Pfad haben muss damit dieser das Skript ausführen kann. Je nachdem wo das Skript also liegt sind dazu je nach Linux-System weitere Maßnahmen wie bspw. das Anpassen von systemd Direktiven nötig.


<?php
// get cmd to be executed from get parameter "command"  
$command = (isset($_GET['command'])) ? $_GET['command'] : "";  
// if cmd is not empty
if ($command !== "" ){  
	// pre flush all buffers
	while(@ob_end_flush());
	// run command
	$proc = popen("$command 2>&1",'r');  
	if ($proc){
		// read command output line by line and flush buffer directly
		while (($buffer = fgets($proc)) !== false){
			echo $buffer;
			@flush();
		}
		// close process pointer
		pclose($proc);
	}
}else{ // cmd is empty show html page with interface instead
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">  
<script>
// init function (setup user control event handlers etc.)
function init(){
	// setup click eventhandler of button
	document.getElementById('btnStart').onclick = (e) => {  
		// call function to with command from input element with id 'txtCommand'  
		LiveGetCommandResult(document.getElementById('txtCommand').value);  
	};
}
// function to get live command output
function LiveGetCommandResult(cmd){
	// reference dom element where command output will be shown
	var elOutput = document.getElementById("result");  
	// create new ajax request object
	var ajax = new XMLHttpRequest();
	// index variable which holds current command output position
	var curPos = 0;
	// event when loading has started
	ajax.onloadstart = () => {
		elOutput.value = "=== Command started ===\n\n";  
	};
	// event called on every respose update
	ajax.onprogress = (e) => {
		// append response part to output element
		elOutput.value += ajax.responseText.substring(curPos);
		// scroll to end of output element
		elOutput.scrollTop = elOutput.scrollHeight;
		// save current output position index
		curPos = ajax.responseText.length;
	};
	// event called when ajax call returns an error
	ajax.onerror = () => {
		elOutput.value += "AJAX-ERROR: " + ajax.statusText;  
	};
	// event on finish
	ajax.onloadend = () => {
		elOutput.value += "\n\n=== Command ended ===\n";  
		elOutput.scrollTop = elOutput.scrollHeight;
	};
	// setup ajax uri with "command" get parameter and URI encoded commandline  
	ajax.open('GET','?command=' + encodeURIComponent(cmd));  
	// start ajax call
	ajax.send();
}
</script>
<style>
#result {
	border:1px solid gray;
	height:400px;
	width:70%;
	overflow: scroll;
}
</style>
</head>
<body onload="init()">  
	<input type="text" id="txtCommand" placeholder="Enter command" value="ping -c 30 -i .5 127.0.0.1" size="50" />  
	<button id="btnStart">Start command</button>  
	<textarea id="result" readonly></textarea>  
</body>
</html>
<?php }

back-to-topVorschau

screenshot

Grüße Uwe