PHP Cronjobs erstellen

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo alle zusammen ich würde gerne ein web website erstellen mit der Ich die ausgänge meines Raspberrys ansteuern kann. Allerdings möchte ich auch eine funktion einbauen mit der man die eingänge per Zeitschaltuhr bedienen kann. Also eine ein und ausschaltzeit festlegen und diese auch wieder ändern zu können. Dieser Code
    [code=php]exec('echo " 00 6 * * * sudo /var/www/html/name der Datei" | crontab -');[/php]
    Funktioniert warum auch immer nicht. Normal über die Konsole kann ich aber Cronjobs erstellen. Bitte um Hilfe.

  • Ich bin mir ziemlich sicher, dass dem Web-Servernutzer die Rechte fehlen etwas in der crontab zu ändern.
    Kann es außerdem sein, dass du den Pfad zu php ("which php" in der Konsole zeigt dir den Pfad) angeben musst? Eine PHP-Datei an sich ist meistens nicht ausführbar.

  • Ein Webserver läuft i.d.R. über einen bestimmten Benutzer: www-data
    Dieser Benutzer hat Standardmäßig keine Rechte die Hardware zu beeinflussen. Auch haben normale Benutzer allgemein kein Recht auf andere Benutzerverzeichnisse zuzugreifen. Generell ist es so das normale Benutzer nicht auf die Verzeichnisse anderer Benutzer zugreifen dürfen - das wäre unsicher und uncool. Der www-data Benutzer sieht also nicht die Dateien in /home/pi/ da er darauf nicht zugreifen kann.

    Jeder Benutzer hat eine eigene Benutzer-Crontab, also auch www-data. ABER:
    Der Benutzer pi darf mit Raspbian ohne Eingabe eines Passwords uneingeschränkt sudo verwenden. Diese besonderen Umstände gelten aus Sicherheitsgründen nicht für den Benutzer www-data und das ist i.d.R. auch gut so, andernfalls besteht ein massives Sicherheitsrisiko!

    Siehe dazu bitte FAQ => Nützliche Links / Linksammlung => sudo webscript


    Setze mal ganz vorne dran noch ein sudo..
    [...] Alternativ kannst du shell_exec() verwenden, dann bekommst du auch mehrere Zeilen ausgegeben.

    Bitte nicht ;)
    shell_exec() ist schlechter als exec() , siehe dazu "sudo webscript" Beitrag. Auch exec(); gibt mehrere Zeilen aus allerdings gibt shell_exec(); nur die Letzte Zeile aus und im Fall eines Fehlers einfach nur FALSE sonst nichts.
    Macht in diesem Fall aber auch nicht den gewünschten Unterschied aus da der Fehler im Crontab-Eintrag selbst liegt. www-data darf kein sudo ohne Password Abfrage nutzen.
    Der Crontabeintrag wird mit Sicherheit vorhanden sein, einfach mal als Benutzer pi den folgenden Befehl ausführen:

    Code
    sudo crontab -u www-data -l

    Würde er sudo ganz vorne dran setzen würde es ebenfalls nicht den gewünschten Effekt erzielen, da dann einfach nur das echo via sudo ausgeführt werden würde, aber entscheidend wäre wenn dann die pipe zum crontab Befehl - allerdings würde es dann in die Crontab des root Benutzers eingetragen werden und dann wäre im Eintrag selbst kein sudo mehr nötig... Aber wie gesagt wird www-data nach einem Password gefragt wenn dieser sudo nutzen möchte. Es wäre ebenfalls ein massives Sicherheitsrisiko wenn jeder Benutzer einfach so sudo nutzen dürfte.
    Bedeutet:
    - Dem www-data Benutzer erlauben sudo ohne Passwordabfrage auszuführen, allerdings bitte nicht uneingeschränkt sondern wenn dann...
    a) nur ein bestimmtes bash Script in dem wiederum verschiedene Befehle stehen. Wird das Script via sudo ausgeführt werden auch alle darin befindlichen Befehle als root ausgeführt.
    b) oder wirklich nur den Befehl bzw Script was über crontab ausgeführt werden soll.

    Wenn a) dann siehe "sudo webscript"
    Wenn b) dann kann die PHP Zeile wie in Beitrag#1 zu sehen, so bleiben. Dann bräuchte er nur "/var/www/html/name der Datei" via sudo erlauben. (aber bitte ohne Leerzeichen!)


    PS: https://www.forum-raspberrypi.de/Thread-php-wecker

  • Auch in PHP sollte man Logik von Anzeige trennen. Alles was Du in der Anzeige (oder auch Eingabe) der Webseite machst, sollte an ein weiteres Script weitergegeben werden, was z.B. die Berechnung durchführt oder in Datenbanken schreibt, dann eine Rückmeldung abgibt und dann einem dritten Script die Entscheidung überlässt, was als nächstes passiert (neue Anzeige, weitere Berechnung ...). Das ist jetzt nur oberflächlich betrachtet, für Genaueres sollte man sich mal verschiedene Programmiermodelle anschauen. Bei PHP bietet sich MVC (Model View Controller) an.
    Das "Zugriffsproblem" kann man relativ gut lösen. Du legst eine Datenbank (oder auch eine Textdatei an), in die Du die Zeiten und erwünschten Aktionen aus dem Eingabeformular eintragen lässt. Das läuft alles mit Zugriff im Dokumentenverzeichnis. Fatal wäre tatsächlich nun außer www-data noch weiteren Zugriff zuzulassen. Lösung ist, ein (oder mehrere Scrips) im /home/pi/phpapps/timer (Beispiel wie ich es mache) abzulegen und dort auf die abgelegten Daten zuzugreifen. Den Nutzer pi (wenn Du ein cron für pi anlegst), der Gruppe www-data zuzuordnen ist bedeutend risikoärmer. Bei einem cron für root ist es noch einfacher. Das Script kannst Du dann alle paar Sekunden per cron mit

    Code
    */1 * * * * php /home/pi/phpapps/timer/timer.php

    aufrufen und die Daten auswerten lassen und stimmen Systemzeit mit der gespeicherten Zeit überein (Zeitbereich größer als Abfrageintervall, nicht exakte Zeit), führt das Script dann die Anweisungen aus.

  • Vielen Dank für alle eure schnellen Antworten. Ich kam leider noch nicht da zu alles auszuprobieren. Ich werde euch aber Informieren sobald ich das gemacht habe. Vielen Dank.

  • Was heißt "via sudo erlauben"? Wenn damit gemeint ist den webscript für www-data zugänglich zu machen funktioniert die methode bei mir nicht. Komicher weße gehört /var/www/ auch pi und nicht www-data. Kann mir da irgendjemand helfen?

  • Hast du Raspbian Jessie?

    Die Standard Konfiguration von apache2 sieht vor das DocumentRoot auf das Verzeichnis /var/www/html/ zeigt - das ist quasi das Hauptverzeichnis der Webdateien. Dieses Verzeichnis gehört dem www-data Benutzer. Wenn das bei Dir nicht der Fall ist hast du daran bereits herumgepfuscht. Allerdings hat das nichts mit "via sudo erlauben" zu tun. Du scheinst aber allgemein auch noch nicht zu verstehen was sudo eigentlich ist oder was das bewirkt?

    Es erscheint mir einfacher wenn du anstatt sturr weiter an sudo festhalten zu wollen meine "wecker.php" oder auch raspiprojekt's Hinweis zu beachten.

  • So hallo. Jetzt habe ich eine Lösung für das Problem gefunden. Ich habe einen Script geschrieben der per Cronjob jede minute einen PHP Script aufruft. Dieser nimmt die Aktuelle Zeit und Subtrahiert diese von der angegebenen Zeit. Wenn das Ergebnis glei Null ist wird eine Led geschaltet.
    [code=php]<?php
    $start = date("H:i");
    $end = @$_POST['end'];
    if ($end != ""){
    file_put_contents("cron.txt", $end);
    }
    else{
    $end = file_get_contents('cron.txt');
    get_time_difference($start, $end);
    }
    function get_time_difference($start_time_o, $end_time_o){
    $start_time = explode(":", $start_time_o);
    $end_time = explode(":", $end_time_o);
       
    $start_time_stamp = mktime($start_time[0], $start_time[1], 0, 0, 0, 0);
    $end_time_stamp = mktime($end_time[0], $end_time[1], 0, 0, 0, 0);
       
    $time_difference = $end_time_stamp - $start_time_stamp;

    if ($time_difference == 0){
    shell_exec("gpio -g mode 21 out");
    shell_exec("gpio -g write 21 1");
    }
    }
    echo '<form action="zeitschaltuhr.php" method="post">
    <input type="text" name="end"><br>
    <input type="submit" value="Erstellen">
    </form>';
    ?>[/php]
    Allerdings habe ich jetzt ein anderes Problem. die Daten aus dem Eingabefeld werden jetzt ja in eine Textdatei geschrieben und anschließend wieder weiterverarbeitet. Nurwenn ich diesen Script jetzt über die Konsole ausführe werden die Dateien aus der Textdatei nicht Berücksichtigt und ich bekomme den Fehler: mktime() expects parameter 1 to be long. Wenn ich die Textdatei aber einzeln über die Konsole ausgebe bekomme ich den Wert ausgegeben und wenn ich die PHP Datei im Browser mit lehrem input Feld zur in derTextdatei definierten Zeit aufrufe wird die Led auch geschaltet. Please :helpnew:

  • Zunächst mal verstehe ich nicht wieso du ein extra Script hast in dem $_POST abgefragt wird? :s Startest du ein Script über die Konsole gibt es keine Möglichkeit den HTML Code also das Eingabeformular auszufüllen. Das macht vorne und hinten kein Sinn.
    Desweiteren ist shell_exec nicht wirklich toll und "gpio" bremst aus.

    Also noch mal zu deinem Vorhaben:

    Du möchtest über eine Webseite verschiedene Zeiten für Crontab einstellen und dann irgendeinen GPIO schalten lassen.

    Du erstellst also eine Datei wie zum Beispiel: /var/www/html/zeitschaltuhr.php => http://codepad.org/ck5rrh0b

  • Gut ich habe die Gpio schaltung jetzt geänder.

    Zitat

    Zunächst mal verstehe ich nicht wieso du ein extra Script hast in dem $_POST abgefragt wird? undefined Startest du ein Script über die Konsole gibt es keine Möglichkeit den HTML Code also das Eingabeformular auszufüllen. Das macht vorne und hinten kein Sinn.

    Zugegebener maßen das ist wirklich nicht schön gelöst. Aber ich wollte alles in einer Datei haben. So dass man mit dieser einen Datei die Zeit über den Webbrowser eistellen kann aber sie auch wenn das Feld lehr ist vom Cronjob aufgerufen werden kann. Allerdings werden ja anscheinend die vorher über das Webinterface in die Textdatei geschriebenen Daten nicht ausgelesen und der Variablen $end zugewiesen. Das seltsame icst aber wenn man den Button im Browser mit lehrem input Feld zur angegebenen Zeit drückt wird die Led geschaltet. Wo liegt der Fehler?

  • Naja du scheinst noch immer nicht meine wecker.php betrachtet zu haben? Da ist auch alles in nur einer Datei. Wird diese über die Konsole ausgeführt übergebe ich ein Parameter/Argument "cron" und prüfe das auch am Anfang der Datei - entsprechend fällt dann die Verarbeitung anders aus.
    Desweiteren hast du für dein <input keine "required" Abfrage sodass das Eingabefeld nicht leer sein darf. Und dann prüfst du auch nicht ob $_POST überhaupt existiert und nicht leer ist. Das @ davor unterdrückt nur Fehlermeldungen ist aber auf diese Weise sehr dirty.

    Also noch ein Vorschlag: /var/www/html/zeitschaltuhr.php => http://codepad.org/CaStwXNr

  • Gut Dankeschön. Im Code hat noch ein $end = $_POST['end']; gefehlt.

    Zitat

    if (isset($_POST['end']) and !empty($_POST['end'])) {
       $end = $_POST['end'];
    file_put_contents("cron.txt", $end);
    echo "OK<br/>";
    }


    So weit so Gut. Doch die Daten die vorher in die textdatei geschrieben wurden werden immer noch nicht ausgelesen. Wenn ich $end fest definiere dann funktioniert es, nicht jedoch so. Wenn ich ein extra Script mache indem ich nur die Daten aus der Textdatei auslese und dann anzeigen lasse funktioniert dass auch. Anscheinend nur nicht wenn ich den Script über die Konsole oder einen Cronjob aufrufen lasse. Hat jemand eine Idee woran das liegen könnte?

Jetzt mitmachen!

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