Een Python-script uitvoeren vanuit PHP

Ik probeer een Python-script vanuit PHP uit te voeren met de volgende opdracht:

exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');

PHP produceert echter gewoon geen uitvoer. Foutrapportage is ingesteld op E_ALL en display_errors is ingeschakeld.

Dit is wat ik heb geprobeerd:

  • Ik heb python2, /usr/bin/python2en python2.7gebruikt in plaats van /usr/bin/python2.7
  • Ik heb ook een relatief pad gebruikt in plaats van een absoluut pad, wat ook niets veranderde.
  • Ik heb geprobeerd de commando’s exec, shell_exec, systemte gebruiken.

Echter, als ik ren

if (exec('echo TEST') == 'TEST')
{
    echo 'exec works!';
}

het werkt prima terwijl shutdown nowniets doet.

PHP heeft de rechten om het bestand te openen en uit te voeren.

EDIT: Dankzij Alejandro kon ik het probleem oplossen. Als je hetzelfde probleem hebt, vergeet dan niet dat je webserver waarschijnlijk/hopelijk niet als root draait. Probeer in te loggen als de gebruiker van uw webserver of een gebruiker met vergelijkbare machtigingen en probeer de opdrachten zelf uit te voeren.


Antwoord 1, autoriteit 100%

Getest op Ubuntu Server 10.04. Ik hoop dat het je ook helpt op Arch Linux.

In PHP gebruik de shell_exec-functie:

Voer opdracht uit via shell en retourneer de volledige uitvoer als een string.

Het retourneert de uitvoer van de uitgevoerde opdracht of NULL als er een fout is
opgetreden of de opdracht levert geen uitvoer op.

<?php 
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
?>

Verifieer in het Python-bestand test.pydeze tekst in de eerste regel: (zie uitleg):

#!/usr/bin/env python

Als je meerdere versies van Python hebt geïnstalleerd, zal /usr/bin/env
zorg ervoor dat de gebruikte tolk de eerste is in uw omgeving
$PAD. Het alternatief zou zijn om iets te hardcoderen als:
#!/usr/bin/python; dat is ok, maar minder flexibel.

In Unix kan een uitvoerbaar bestand dat bedoeld is om te worden geïnterpreteerd, aangeven:
welke tolk te gebruiken door een #! aan het begin van de eerste regel,
gevolgd door de interpreter (en eventuele vlaggen).

Als je het over andere platforms hebt, geldt deze regel natuurlijk niet
toepassen (maar die “shebang-regel” kan geen kwaad, en zal helpen als je ooit
kopieer dat script naar een platform met een Unix-basis, zoals Linux,
Mac, enz.).

Dit is van toepassing wanneer u het in Unix uitvoert door het uitvoerbaar te maken
(chmod +x myscript.py) en vervolgens direct uitvoeren: ./myscript.py,
in plaats van alleen myscript.py python

Om een uitvoerbaar bestand te maken op unix-type platforms:

chmod +x myscript.py

Ook Python-bestand moet de juiste rechten hebben( uitvoering voor gebruiker www-data / apache als PHP-script in browser of curl draait)
en/of moet “uitvoerbaar” zijn. Ook moeten alle opdrachten in het .py-bestand de juiste rechten hebben.

Genomen uit de php-handleiding:

Een snelle herinnering voor degenen die shell_exec proberen te gebruiken op een
unix-type platform en lijkt het niet werkend te krijgen. PHP wordt uitgevoerd als
de webgebruiker op het systeem (meestal www voor Apache), dus u moet
zorg ervoor dat de internetgebruiker rechten heeft op alle bestanden of
mappen die u probeert te gebruiken in de opdracht shell_exec.
Anders lijkt het alsof het niets doet.


Antwoord 2, autoriteit 15%

Ik raad aan om passthrute gebruiken en de uitvoerbuffer direct af te handelen:

ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean(); 

Antwoord 3, autoriteit 9%

Als je de retourstatus van de opdracht wilt weten en de volledige stdout-uitvoer wilt, kandaadwerkelijk execgebruiken:

$command = 'ls';
exec($command, $out, $status);

$outis een array van alle regels. $statusis de retourstatus. Erg handig voor het opsporen van fouten.

Als je ook de stderr-uitvoer wilt zien, kun je spelen met proc_openof voeg eenvoudig 2>&1toe aan je $command. Dit laatste is vaak voldoende om dingen werkend te krijgen en veel sneller te “implementeren”.


Antwoord 4, autoriteit 4%

Alejandro heeft het voor elkaar gekregen door verduidelijking toe te voegen aan de uitzondering (Ubuntu of Debian) – ik heb niet de vertegenwoordiger om aan het antwoord zelf toe te voegen:

sudoers-bestand:
sudo visudo

uitzondering toegevoegd:
www-data ALL=(ALL) NOPASSWD: ALL


Antwoord 5, autoriteit 4%

Om te verduidelijken welk commando te gebruiken op basis van de situatie

exec()– Voer een extern programma uit

system()– Voer een extern programma uit en geef de uitvoer weer

passthru()– Voer een extern programma uit en geef onbewerkte uitvoer weer

Bron: http://php.net/manual/en/function.exec. php


Antwoord 6, autoriteit 3%

In mijn geval moest ik een nieuwe map aanmaken in de wwwdirectory genaamd scripts. Binnen scriptsheb ik een nieuw bestand toegevoegd met de naam test.py.

Vervolgens gebruikte ik sudo chown www-data:root scriptsen sudo chown www-data:root test.py.

Toen ging ik naar de nieuwe directory scriptsen gebruikte sudo chmod +x test.py.

Mijn test.py-bestand ziet er zo uit. Let op de verschillende Python-versie:

#!/usr/bin/env python3.5
print("Hello World!")

Vanuit php doe ik nu dit:

$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);

En je zou het moeten zien: Hallo wereld!


Antwoord 7, autoriteit 3%

De bovenstaande methoden lijken ingewikkeld. Gebruik mijn methode als referentie.

Ik heb deze twee bestanden:

  • run.php

  • mkdir.py

Hier heb ik een HTML-pagina gemaakt die een GO-knop bevat. Telkens wanneer u op deze knop drukt, wordt er een nieuwe map gemaakt in de map waarvan u het pad hebt genoemd.

run.php

<html>
 <body>
  <head>
   <title>
     run
   </title>
  </head>
   <form method="post">
    <input type="submit" value="GO" name="GO">
   </form>
 </body>
</html>
<?php
	if(isset($_POST['GO']))
	{
		shell_exec("python /var/www/html/lab/mkdir.py");
		echo"success";
	}
?>

Antwoord 8

Dit is zo triviaal, maar ik wilde gewoon iedereen helpen die Alejandro’s suggestie al had gevolgd maar deze fout tegenkwam:

sh: blabla.py: opdracht niet gevonden

Als iemand die fout is tegengekomen, moet Alejandro een kleine wijziging in het php-bestand aanbrengen:

$command = escapeshellcmd('python blabla.py');

Antwoord 9

Geïnspireerd door Alejandro Quiroz:

<?php 
$command = escapeshellcmd('python test.py');
$output = shell_exec($command);
echo $output;
?>

Python moet worden toegevoegd en het pad is niet nodig.


Antwoord 10

Alle bovenstaande opties creëren een nieuw systeemproces. Wat een prestatie-nachtmerrie is.
Voor dit doel heb ik de PHP-module samengevoegd met “transparante” aanroepen naar Python.

https://github.com/kirmorozov/runpy

Het kan lastig zijn om te compileren, maar het bespaart systeemprocessen en laat je Python-runtime behouden tussen PHP-aanroepen.

Other episodes