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.
PHP Cronjobs erstellen
-
DreiDe -
2. Juni 2016 um 07:12 -
Erledigt
Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
-
-
PHP Cronjobs erstellen? Schau mal ob du hier fündig wirst!
-
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. -
Setze mal ganz vorne dran noch ein sudo..
Schau dir auch die ausgabe von exec() mal an. Alternativ kannst du shell_exec() verwenden, dann bekommst du auch mehrere Zeilen ausgegeben. -
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: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!) -
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 mitaufrufen 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 -
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
PHP
Alles anzeigen<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="de"> <head> <title>Zeitschaltuhr</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="robots" content="DISALLOW"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <style type="text/css"> body { background-color: #000000; color: white; } .wrapButtons { text-align: center; font-size: 60px; font-family: "Verdana"; } .currentClock { font-size: 25px; font-weight: 600; padding-right: 15px; } </style> <script type="text/javascript"> function addZero(i) { if (i < 10) { i = "0" + i; } return i; } function Clock() { var x = document.getElementById("currentClock"); var time = new Date(); var h = addZero(time.getHours()); var m = addZero(time.getMinutes()); var s = addZero(time.getSeconds()); x.innerHTML = h + ":" + m + ":" + s; } setInterval(function(){ Clock() }, 1000); </script> </head> <body onLoad="Clock();"> <div style="float:right; margin-top:-4px;"> <span id="currentClock" class="currentClock"></span> </div> <br/> <hr noshade size="5"> <?php $ZeitenDatei = "txt.cron"; // Schreibe neue Schaltzeit in Datei if (isset($_GET['hour'])) { $HOUR = sprintf("%02d", $_GET['hour']); if (!isset($_GET['min'])) { $MINUTE = 00; } else { $MINUTE = sprintf("%02d", $_GET['min']); } if (!isset($_GET['day'])) { $DAY = date('d'); } else { $DAY = sprintf("%02d", $_GET['day']); } if (!isset($_GET['mon'])) { $MONTH = date('m'); } else { $MONTH = sprintf("%02d", $_GET['mon']); } file_put_contents($ZeitenDatei, "$HOUR:$MINUTE $DAY.$MONTH\n", FILE_APPEND); } if (file_exists($ZeitenDatei)) { $Data = file($ZeitenDatei); if (!empty($Data)) { echo "Erstellte Zeit(en):\n<br/>"; foreach($Data AS $line_num => $line) { echo $line ."<br/>"; } } } echo "<br/>"; ?> <!-- Zeit Erstellen --> <form action="zeitschaltuhr.php" method="GET"> <input type="number" min="0" max="23" name="hour" required="required"> : <input type="number" min="0" max="59" name="min"> <input type="submit" value="Erstellen"> </form> </body> </html> [/php] Das sollte als Grundgerüst zum erstellen reichen.. wenn du genaueres wissen willst siehe "Wecker" in Beitrag#4 Dann erstellst du ein PHP-Script was jede Minute über crontab ausgeführt wird, wie zum Beispiel: /var/www/html/cron.php => http://codepad.org/CERciYw0 [code=php] <?php $ZeitenDatei = "txt.cron"; if (!file_exists($ZeitenDatei)) { exit(); } init_GPIO("21", "out"); $HOUR = date("H"); $MINUTE = date("i"); $DAY = date("d"); $MONTH = date("m"); $Data = file($ZeitenDatei); foreach($Data AS $line_num => $line) { if ($line == "") { continue; } // Format: 23:59 31.12 $lineData = str_replace(PHP_EOL, '', explode(" ", $line)); $Time = explode(":", $lineData[0]); $Date = explode(".", $lineData[1]); if ($Date[0] == $DAY AND $Date[1] == $MONTH) { if ($Time[0] == $HOUR AND $Time[1] == $MINUTE) { echo "Alarm!\n"; einschalten("21"); // Delete Alert. deleteLine($ZeitenDatei, $line_num); } } } //------------------------------------------------------ function deleteLine($file, $lineNum) { $NewLines = array(); $lines = file($file); foreach($lines AS $lnum => $line) { if ($lnum != $lineNum) { $NewLines[] = $line; } } $handle = fopen($file, "w"); foreach($NewLines as $line) { fwrite($handle, $line+"\n"); } fclose($handle); } function init_gpio($pin, $direction) { $handle = @fopen("/sys/class/gpio/export", 'a'); @fwrite($handle, $pin); @fclose($handle); $handle = @fopen("/sys/class/gpio/gpio".$pin."/direction", 'a'); @fwrite($handle, $direction); @fclose($handle); } function einschalten($pin) { $handle = @fopen("/sys/class/gpio/gpio".$pin."/value", 'a'); @fwrite($handle, "1"); @fclose($handle); } function ausschalten($pin) { $handle = @fopen("/sys/class/gpio/gpio".$pin."/value", 'a'); @fwrite($handle, "0"); @fclose($handle); } ?> [/php] Was es mit dem GPIO schalten auf sich hat siehe hier: https://www.forum-raspberrypi.de/Thread-php-anleitung-zum-schalten-von-gpio?pid=179320#pid179320 Und dann erstellst du einen Crontabeintrag: [code]* * * * * /usr/bin/php /var/www/html/cron.php >/dev/null 2>&1
-
Gut ich habe die Gpio schaltung jetzt geänder.
ZitatZunä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
PHP
Alles anzeigen<?php if (isset($argv[1]) AND (!empty($argv[1]) AND $argv[1] == "cron")) { if (!file_exists("cron.txt")) { exit(); } $start = date("H:i"); $end = file_get_contents("cron.txt"); if (get_time_difference($start, $end) == 0) { if (!file_exists("/sys/class/gpio/gpio21")) { file_put_contents("/sys/class/gpio/export", "21"); usleep(200000); //Programm-Verzoegerung in Mikrosekunden: 0.2s file_put_contents("/sys/class/gpio/gpio21/direction", "out"); } file_put_contents("/sys/class/gpio/gpio21/value", "1"); } exit(); } if (isset($_POST['end']) and !empty($_POST['end'])) { file_put_contents("cron.txt", $end); echo "OK<br/>"; } 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; return $time_difference; } ?> <form action="zeitschaltuhr.php" method="post"> <input type="text" name="end" required="required"><br/> <input type="submit" value="Erstellen"> </form> [/php] Crontabeintrag: [code]* * * * * /usr/bin/php /var/www/html/zeitschaltuhr.php cron >/dev/null 2>&1
-
Gut Dankeschön. Im Code hat noch ein $end = $_POST['end']; gefehlt.
Zitatif (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? -
Tipp: Absolute Pfade für cron.txt setzen.
-
Super. Danke.
Es funktioniert jetzt alles.
Jetzt kann ich behruhigt schlafen gehen
Jetzt mitmachen!
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!