Programm via Webserver starten geht nicht

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,
    vermutlich habe ich ein Rechteproblem, darum stelle ich hier die Frage. Bin mir aber nicht sicher.
    Also, ich habe ein kleines Programm geschrieben, das ich via Webserver aufrufen möchte. Das Programm "f1h.sh" als solches läuft.
    Als nächstes habe ich ein php-Skript geschrieben, das es starten soll. Und dieses Skript soll von einer Seite "rollo.html" aufgerufen werden. Soweit der Plan, wenn es einfacher geht, bin ich für jeden Tipp dankbar.

    Nun aber zu meinem Problem.
    Das php-Skript "f1h.php" liegt in /var/WWW gehört WWW-data/WWW-data mit 755
    und sieht so aus:

    PHP
    <?php 
    shell_exec (´/home/pi/skripte/fhem/f1h.sh´) ;
    header("Location:rollo.html") ;
    ?>


    Es passiert nichts, außer dass ich zum Schluss wie gewünscht auf der rollo.html lande.

    Das f1h.sh gehört pi/pi mit 755 und sieht so aus:

    Bash
    #!/bin/bash
    #
    # GPIO Zuordnung    Farbe       Relaisfunktion
     rel1=gpio17    # R1 schwarz    1 runter
     rel2=gpio27    # R2 wei▒^▒             1 hoch
     echo "0" > /sys/class/gpio/$rel1/value
     echo "1" > /sys/class/gpio/$rel2/value
     sleep 30
     echo "0" > /sys/class/gpio/$rel2/value
    exit 0

    Ich habe bereits die Rechte folgendermaßen vergeben:

    Zitat

    sudo chmod g+s /var/www
    sudo chmod 775 /var/www
    sudo chown -R www-data:www-data /var/www

    Entweder Programmierfehler oder habe keine Rechte zum Ausführen, könnt ihr mir helfen?

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,


  • ..., wenn es einfacher geht, bin ich für jeden Tipp dankbar.

    M. E. ist es einfacher (leichtgewichtiger) mit socat (evtl. mit sudo wenn erforderlich; aus der rc.local (ohne "&" und ohne sudo) immer als root), über das Internet/(W)LAN ein Script zu starten. Z. B.:

    Auf dem Pi:

    Code
    sudo apt-get install socat
    (sudo) socat -u -T 1 TCP4-LISTEN:55555,reuseaddr,fork EXEC:</Pfad/dein-Script-auf-dem-Pi> &


    Auf dem Rechner im Internet oder im (W)LAN:

    Code
    nc -v -n -w 1 <IPv4-Adresse> 55555

    EDIT:

    Statt "nc -v -n -w 1 <IPv4-Adresse> 55555" kannst Du auch im Browser deines Smartphones:

    Code
    <IPv4-Adresse>:55555


    benutzen.

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

    Einmal editiert, zuletzt von rpi444 (31. Juli 2014 um 11:58)

  • Vielen dank für den Tipp. Bin gerade unterwegs und kann nicht nach socat recherchieren.
    Bleibt das Problem, dass das php-script nicht das *.SH startet oder starten kann. Leider sehe ich keine Fehlermeldung.
    Das sind allerdings auch meine allerersten Versuche mit HTML und PHP und die Codes habe ich kreativ übernommen.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,


  • Es passiert nichts, ...


    Was müsste passieren?


    ... oder habe keine Rechte zum Ausführen, ...

    Das kannst Du mit einer temporären Zeile in deinem Script feststellen. Z. B.:

    Code
    /usr/bin/logger "Hallo, ich bin dein Script."


    und nach dem "Ausführen", auf dem Pi:

    Code
    cat /var/log/syslog | grep -i hallo

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

    Einmal editiert, zuletzt von rpi444 (31. Juli 2014 um 10:01)

  • Da fällt mir noch was ein.
    Eigentlich schaltet bei mir ja selbst das php-skript nicht die GPIOs, sondern ruft lediglich ein Programm auf (r1h.SH), das die GPIOs schaltet.
    Ist das irgendwie wichtig für mein Problem?

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Ja ist wichtig.

    Webserver startet als Root und wechselt dann zum User www-data, der sich dann auf Port 80 setzt. Alles was dann im Webserver passiert, wird mit den Rechten von www-data gemacht.
    Jetzt benutzt Du php und wirst das über einen Socket aufrufen, dahinter steckt dann der PHP Prozess, der sehr wahrscheinlich auch als User www-data gestartet ist.

    Bei mir z.B. so:

    Code
    www-data 10852  1.0  1.2 240200 51316 ?        S    09:11   1:33  \_ php-fpm: pool www

    Das PHP Script wird also vom User www-data ausgeführt und der darf dann das r1h.SH aufrufen und vererbt auch wieder seine Rechte an den Systemcall (shell_exec), was dann nicht funktioniert, da www-data nicht auf das Zeug für GPIO zugreifen darf.

  • Ja, ich glaube auch, dass php die GPIOs nicht schalten darf und habe eine leichte Ahnung, was ihr meint.
    Aber wie komme ich aus der Zwickmühle?

    Code
    pi@fhem2 ~/skripte/fhem $ sudo usermod -G gpio -a www-data
    pi@fhem2 ~/skripte/fhem $ sudo /etc/init.d/lighttpd restart
    [ ok ] Stopping web server: lighttpd.
    [ ok ] Starting web server: lighttpd.


    habe ich durchgeführt.

    Code
    pi@fhem2 ~/skripte/fhem $ id www-data
    uid=33(www-data) gid=33(www-data) Gruppen=33(www-data),1003(gpio)
    Code
    pi@fhem2 ~/skripte/fhem $ sudo -u www-data php -r 'exec("echo 17 > /sys/class/gpio/export"); if (file_exists("/sys/devices/virtual/gpio/gpio17")) { echo "yea "; }'


    Sollte auch IO sein.

    Und inzwischen kommt die Systemmeldung 403 Forbidden. Das ist neu, aber ein Schritt in die falsche Richtung.
    Sollte ich das System noch mal völlig neu aufsetzen, weil ich jetzt mehr kaputt gemacht habe?
    Jetzt ist sogar die einfache info.php verboten:

    PHP
    <?php
    phpinfo();
    ?>

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Nein nicht aufsetzen, das ist Linux und man muss nicht wegen jedem kleinem Fehler neu installieren, das fixt man einfach.

    Ich würde eh immer Webinterface und das Ausführen von Scripten aus dem Webserver trennen.
    Lass das Script einfach eine Datei schrieben ohne Inhalt und der Name ist der Befehl der ausgeführt werden soll.

    Code
    <?PHP
    fopen($fh,"/tmp/gpio_web_rollo_rauf.cmd"); 
    close $fp
    ?>

    Ein 2. Script was z.B per Cron läuft checkt ob eine der Dateien vorhanden ist.
    Wenn /tmp/gpio_web_rollo_rauf.cmd vorhanden starte das Rollo raud Script, wenn /tmp/gpio_web_rollo_runter.cmd wird das Rollo Script zum runter fahren ausgeführt.
    Anschliessend wird das File wieder entfernt.

    So kann Dir keiner etwas einschleusen, was dann Dinge tut, die Du eigentlich nicht willst.

    Die Steuerung über das Webinterface ist dann auch schön getrennt vom Systembefehl. Damit ein falscher Befehl, wenn Du eigentlich Rollos runter fahren wolltest aber den hochfahren Button getroffen hast, kannst Du dann auch per Date checken welcher wirklich der letzte Befehl war und verhindern das erst unnötig hoch und dann erst runter fährt.

    Andere werden dir ggf. vorschlagen per Exec ein "sudo /path/to/script.sh" zu machen und dafür dann in die sudoers dann einzutragen das der User www-data das Script ausführen darf ohne Passwort. Ist unschön und kann zu schnell für andere Sachen ausgenutzt werden.

  • Naja, fixen ist gut, wenn man weiß, was man will, ... und was man tut ;)

    PHP geht offenbar nicht mehr, weil die PHP-Aufrufe inzwischen gänzlich verboten sind. Könnte ein

    Code
    sudo /etc/init.d/php5 stop
    sudo apt-get remove php5
    sudo pat-get install php5


    weiterhelfen?

    Dass man mit sudoers und ohne Passwort am Webserver nichts machen soll, habe ich schon gelesen und verinnerlicht.

    Deinen vorgeschlagenen Weg mit der Trennung von Webinterface und Webserver find ich sehr gut, aber das wie habe ich nicht verstanden.
    Gibt es dafür ein Schlagwort, wo man noch mal recherchieren kann? Oder ein Beispiel, dass ich mal sehen kann, was gemeint ist. Wie gesagt, das sind meine allerersten Schritte auf dem Gebiet, da sollte es am Anfang nucht zu kompliziert werden.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Wenn du den Fehler nicht suchen willst sondern durch Neuinstallation erschlagen, dann könnte das fast helfen. anstatt des "remove" solltest du jedoch "purge" verwenden.
    remove - löscht alle Programmdateien
    purge - löscht alle Programmdateien inklusive der Konfigurationen (und wenn, dann ist da das Problem ;) )

  • OK, ich habe PHP5 mit purge deinstalliert und dann neu installiert. Das funktioniert jetzt wieder. Ich war etwas voreilig, mit System neu aufsetzen wollen. Danke, dass ihr mich zurück gehalten habt ;)

    Aber mein eigentliches Problem, dass das PHP-Script kein Script zum Steuern von GPIOs startet, ist immer noch vorhanden.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Dann schreib ein PHP Script und ein anderes zum abarbeiten der Jobs vom Webfrontent.
    ok, ok, $Freunding liegt hier eh auf der Couch und schnarcht. ;)

    Hier bitte schön.

    rollo.php

    Code
    <?PHP
    $handle = fopen("rollo.asc", "w");
    close($handle);
    ?>

    rollo.sh

    Das Shellscript rollo.sh speichern dann ausführbar machen: chmod +x Rollo.sh
    Dann kannst Du das einfach starten mit: ./rollo.sh start
    Starten, in den Hintergrund schieben und vom PI ausloggen: nohup ./rollo.sh start &
    Oder noch bessern: screen -S rollo ./rollo.sh start

    Screen wieder schliessen mit den Tasten ctrl+a und d drücken. Das legt den screen in den Hintergrund.
    Gucken welche Screens offen sind: screen -ls
    Den rollo Screen nach vorne holen: screen -r rollo
    Du kannst also das Script im Screen starten und dich dann auch wieder ausloggen.
    Um das Script zu beenden musst Du nicht im Screen sein, das Script kannst Du einfach mit dem Parameter stop beenden und dann ist es auch im Screen aus. Dabei wird dann auch der Screen beendet.

    Wenn Du wissen willst ob es läuft: ./rollo.sh status
    Wenn Du es soppen willst: ./rollo.sh stop

  • Kurze Statusmeldung meinerseits.
    Inzwischen habe ich Dank ubuntuusers.de einiges über Prozesssteuerung gelernt. Außerdem musste ich Screen nachinstallieren und habe dann erst mal begriffen, was du meintest ;)

    Ehe ich mich in das rollo.sh wühle und womöglich was Falsches mache, noch einige prinzipielle Fragen.

    Ich bin als pi unterwegs und die Dateien liegen in einem Unterordner von /home/pi , oder könnte/muss die rollo.php im Ordner /var/WWW liegen?

    Die rollo.php rufe ich dann von der Homepage unter /var/WWW auf, oder?

    Ich muss für jede Aktion, also [Rollo1 hoch; Rollo1 runter; Rollo2 hoch; ...] je eine solche *.php und *.sh erstellen?

    Die rollo.sh starte ich später immer beim Hochfahren mittels Crontab? Müssen da noch Parameter übergeben werden?

    Doch schon 2 Fragen zum eigentlichen Skript.
    Die eigentliche Aktion, was mit den GPIOs passiert, steht im Bereich function run() in der do-Schleife, was jetzt auskommentiert wurde, nicht wahr?
    Könnte ich dort statt dessen mit "shell_exec /pfad/zur/Datei.sh" die eigentliche Runterfahr-Routine aufrufen? Das sind 7-Zeiler, die ich auch bei der automatischen Steuerung der Rollos verwende (was hier auskommentiert wurde und ich inzwischen ausgelagert hatte)

    Wird der Tastendruck nur alle 5 Sekunden ausgewertet, oder warum ist das sleep = 5 in der Schleife?

    Bitte entschuldige, das sind ne menge Fragen, aber das ist Neuland für mich und ich möchte einigermaßen verstehen, was in meinem Haus abläuft :)

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Moin,

    immer diese vielen Fragen ;)

    Ja scripte kommen in /var/www, das rollo.sh kannst Du auch ausserhalb speichern, dann kann Dir wenigstens keiner dazwischen funken und irgend welche Lücken ausnutzen. Aber ja Pack erst einmal alles in /var/www, später kannst Du dann ja noch alles umsortieren und anpassen.

    Das Beispiel war jetzt nur für das runter fahren. Das kannst man aber schnell erweitern, so das Du auch weiter nur noch ein Script hast. http://xxx.xxx.xxx.xxx/rollo.php?do=rollo1&task=up und im PHP Script dann abfragen und entsprechend abarbeiten.

    Das Sleep 5 ist deshalb drin, da es sonst innerhalb von Millisekunden ein paar mal durch laufen würde und jedes mal auf das Filesystem zugreift um schauen, ob eine Action vorhanden ist. Du kannst das weiter mit der Datei machen oder später wenn alles andere klappt auch erweitern. Zum Beispiel würde da besser "named pipes", Das sind Dateien im Filesystem, die aber keine richtigen Files sind, sondern dafür benutzt werden können Daten zwischen 2 Programmen auszutauschen.

    Das Bash Script würde eine solche Datei anlegen und dann drauf zugreifen und warten das etwas rein kommt.
    Das PHP.Script würde dann einfach wie in einer Datei dort Befehle rein schreiben. Sieht das Bash Script das dann, wird es ausgewertet und ausgeführt.
    Das ganze ist etwas Ressourcen schonender.

    Deine Zeilen in der Funktion run() habe ich nur zum testen auskommentiert, kann wieder rein oder wie Du schon fragst auch ausgelagert werden.

    Das rollo.sh kannst Du manuell starten oder auch per init beim booten. Wenn per init musst Du nur noch den richtigen LSB Header am Anfang einbauen, das können wir dann aber später noch machen bzw. Du dann noch mal nachfragen.

  • Langsam komme ich dahinter.
    Also die rollo.sh wird (als Dienst??) gestartet und wartet auf ein Ereignis.
    Nämlich, dass in dem Ordner, in dem sie liegt, die Datei "rollo.asc" erscheint. Erscheint sie, wird der per Webbefehl geklickte Befehl ausgeführt. Später muss ich also nur für jedes Ereignis eine weitere rollo-x.php erstellen und in der rollo.sh im Bereich function run die entsprechenden while-do-Schleifen erweitern. Toll :bravo2:

    Aber ein Grundlagenproblem habe ich noch:

    Code
    pi@fhem2 /var/www $ ./rollo.sh start
    PID: 6001
    ./rollo.sh: Zeile 22: rollo.pid: Keine Berechtigung


    Das führt vermutlich auch zu:

    Code
    rm: regul▒re leere Datei (schreibgesch▒tzt) ▒rollo.asc▒ entfernen? y
    rm: Entfernen von ▒rollo.asc▒ nicht m▒glich: Keine Berechtigung


    Ich habe bereits die rollo.sh dem User WWW-data übergeben, hat aber nichts geholfen.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!