PHP exec() führt Befehl unendlich oft aus

CitroenDsVier

Lt. Commander
Registriert
Dez. 2013
Beiträge
1.885
Hallo zusammen,

in einem aktuellen Projekt verwende ich eine Website, um ein java-Backend auf einem Raspberry Pi zu starten. Diese sieht ungefähr so aus:
PHP:
<?php
     exec("sudo java -jar /path/to/jar.jar &");
?>
<!DOCTYPE html>
<html>
...

Aus mir unerklärlichen Gründen (die Seite wird nur 1x aufgerufen!) werden innerhalb kürzester Zeit dutzende Prozesse mit der .jar gestartet.

Der Nutzer www-data hat in der sudoers Datei die Erlaubnis bekommen, auf /usr/bin/java zuzugreifen.

Kann mir hier Jemand zu weiterhelfen?


Nachtrag: Erwähnen sollte ich vielleicht noch, dass die Seite im Browser nicht fertig lädt, also php nicht zu terminieren scheint. Zumindest innerhalb der ersten Minute, danach habe ich immer abgebrochen, weil der Raspi natürlich unendlich langsam wurde.
 
Zuletzt bearbeitet: (Grund: Nachtrag)
Ui. Ui. Ui.

Php...sudo...exec... einfach nein
Warum musst du das Backend unbedingt von php aus starten?

Praktisch aber: Ich erwarte mir irgendwie, dass PHP da wohl einfach wartet bis der Prozess vorbei ist. Obwohl du hinten & dran hast.
 
Zeroflow schrieb:
Warum musst du das Backend unbedingt von php aus starten?
Welche simple Alternativen gibt es?

Zeroflow schrieb:
Praktisch aber: Ich erwarte mir irgendwie, dass PHP da wohl einfach wartet bis der Prozess vorbei ist. Obwohl du hinten & dran hast.
Das wäre ja nicht schlimm, wenn die jar nur 1x gestartet würde. Dann würde die Seite einfach nie fertig laden.
 
Das hängt von deiner Definition von simpel ab, aber da es ja ein RPi ist und damit vermutlich dein System, würde ich einen Service der im Hintergrund laufen soll auch einfach über systemd einrichten (sofern dein System systemd verwendet). Das kann man dann auch so einrichten dass der Service nach einem Crash neugestartet wird.
 
  • Gefällt mir
Reaktionen: RalphS
Ich zitiere mal aus der PHP-Seite von exec():

Note: If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

Also scheint dein exec wirklich einfach auf das Ende zu warten.
 
  • Gefällt mir
Reaktionen: Mihawk90
Mihawk90 schrieb:
Das hängt von deiner Definition von simpel ab, aber da es ja ein RPi ist und damit vermutlich dein System, würde ich einen Service der im Hintergrund laufen soll auch einfach über systemd einrichten (sofern dein System systemd verwendet). Das kann man dann auch so einrichten dass der Service nach einem Crash neugestartet wird.
Habe ich gerade vesucht, ganz seltsames Verhalten. Service eingerichtet und gestartet nach
dieser Anleitung, mit htop gecheckt, ob die jar läuft. Htop aktualisiert sein Bild ja etwa alle halbe Sekunde, ich habe immer abwechselnd alle halbe Sekunde 0 java-Prozesse und dann wieder ca. 10-15 java-Prozesse (derselben jar) gesehen.
Dazu muss ich sagen: die jar startet sich nicht nochmal selbst o.Ä. Der Befehl java -jar /path/to/jar.jar startet die jar und alles läuft normal.

Exterior schrieb:
Also scheint dein exec wirklich einfach auf das Ende zu warten.
Und warum wird die .jar dann etliche Male gestartet?


Wäre es nicht möglich, mittels
PHP:
<?php
     exec("sudo java -jar /path/to/jar.jar > output.txt &");
?>
den output in eine Datei zu leiten? Oder würde php dann trotzdem auf das Ende der .jar warten?



Nachtrag: ein "java -jar /path/to/jar.jar > output.txt" startet die .jar ebenfalls etliche Male. :confused_alt: :confused_alt: Gerade festgestellt: exakt 20x. Dann geht auch die cpu-load runter.
 
Sudo => raus
exec => auch raus

Wie schon geschrieben: Service einrichten. Warum soll das die Webanwendung starten? Das soll schon laufen und die Webanwendung soll damit kommunizieren.

Ausnahme: das ist von der Programmierlogik her eher eine Batchverarbeitung (vorne Input rein, hinten Output raus) in welchem Fall man aber kein sudo benötigt.
 
@RalphS: Richtig, der Service soll eigentlich schon laufen. Nur für den Fall, dass er noch nicht läuft, soll er gestartet werden.
Ein Service ist vermutlich die schönere Variante, das stimmt. Die .jar hat wenig mit Batch-Verarbeitung zu tun, das ist eine REST-Api.

Bleibt offen, warum der Service die .jar 20x startet...
 
CitroenDsVier schrieb:
@RalphS: Richtig, der Service soll eigentlich schon laufen. Nur für den Fall, dass er noch nicht läuft, soll er gestartet werden.
Das würde in dem Fall aber eh nicht funktionieren.
Da du ja keinen Check drin hast ob der Service schon läuft, würde die jar ohnehin bei jedem Aufruf gestartet werden.
 
Ist folgende .service-Datei denn richtig konfiguriert?

Code:
[Unit]
Description=Backend Service
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
User=pi
ExecStart=/usr/bin/java java -jar /home/pi/lightAlarm/lightAlarm.jar

[Install]
WantedBy=multi-user.target
Ergänzung ()

Mihawk90 schrieb:
Das würde in dem Fall aber eh nicht funktionieren.
Da du ja keinen Check drin hast ob der Service schon läuft, würde die jar ohnehin bei jedem Aufruf gestartet werden.
Doch, das wird an anderer Stelle gemacht. Die oben beschriebene Seite wird nur aufgerufen, wenn die jar nicht läuft und gestartet werden soll. Aber ich versuche es jetzt erst einmal mit der service-Variante.
 
Im Sinne einer sauberen Client-Server architektur hat service start exakt gar nichts dort zu suchen.

Wenn der JAVA-Service nicht läuft: HTTP 50x werfen.
 
Zurück
Oben