Shell skript über Url ausführen?
Hallo,
Ich habe einen Raspberry Pi.
Auf diesem kann ich per Befehl eine Funksteckdose steuern.
Jetzt habe ich mir ein Shell skript geschrieben, dass beim aufrufen die Steckdose einschaltet.
Jetzt möchte ich, dass dieses Skript aufgerufen wird wenn ich eine bestimmte Url aufrufe.
z.B. bei: 192.168.x.x/Dosen/Dose1an wird die erste Steckdose eingeschaltet.
Wie mache ich das?
2 Antworten
Du kannst einen HTTP-Server starten, über den du sie dann steuern kannst. Ich bevorzuge dafür allerdings Node.js, da man da praktisch nichts konfigurieren muss und auch in JavaScript (also eventbasierend) programmieren kann. Das ist außerdem auf dem Raspi auch schon vorinstalliert (eine STEINZEITVERSION aber doch node).
Das Skript, dass ich dir geschrieben habe, habe ich bis Node v0.10.1 getestet. Ich denke, älter wird dein Raspi-Node auch nicht sein.
Es nutzt die Pakete child_process, fs und http. Diese können mit npm install <paketname> installiert werden. Es lauscht auf Port 8080. Um es auf den HTTP-Standard-Port (80) zu starten, müsste es mit sudo ausgeführt werden. Der Port kann in der letzten Zeile geändert werden.
Die Pakete kannst du so installieren:
npm install http
npm install fs
npm install child_process
Hier das Skript, dass den HTTP-Server startet:
const exec = require('child_process').exec;
const fs = require('fs');
var server = require('http').createServer(function(request, response) {
cmd = '';
fs.createReadStream('cmd.txt')
.on('data', function(data) {
cmd += data;
})
.on('end', function() {
cmd = cmd.match(/"[^"]+"/g);
if(cmd === null) return response.end('FEHLER!\n=======\nDatei cmd.txt ist leer oder ungueltig.\n\nBearbeiten kannst du die Datei beispielsweise mit dem Editor "nano".\nGib also einfach in die Konsole den Befehl "nano cmd.txt" ein um sie zu bearbeiten.\n\nDie Befehle und URLs muessen in doppelten Anfuehrungszeichen gespeichert werden.\nDie URLs müssen auserdem mit einem Slash (/) beginnen.\nBeispiel:\n\n"/dies/ist/ein/beispiel" "ls -la"\n\nDiese Zeile wuerde bei Aufruf der URL /dies/ist/ein/beispiel den Befehl ls -la ausfuehren also den Inhalt des Verzeichnisses anzeigen.', 'utf8');
if(cmd.indexOf('"' + request.url + '"') === -1 || cmd[cmd.indexOf('"' + request.url + '"') + 1] === void(0)) return response.end('Befehl/URL nicht gefunden!');
cmd = cmd[cmd.indexOf('"' + request.url + '"') + 1];
var child = exec(cmd.substr(1, cmd.length - 2));
child.stdout.pipe(response)
child.stderr.pipe(response)
})
.on('error', function (error) {
if(error.code === 'ENOENT') return response.end('Datei "cmd.txt" existiert nicht/wurde nicht gefunden!\n\nBitte mit touch cmd.txt erstellen.');
response.end('Fehler beim öffnen der Datei "cmd.txt"\nFehlercode: ' + error.code);
})
})
.listen(8080);
Und hier wie du es nutzen kannst:
In die Datei cmd.txt schreibst du die URLs zusammen mit den Befehlen rein. URL und Befehl müssen dabei in doppelten Anführungszeichen stehen. Alles was nicht in doppelten Anführungszeichen steht wird ignoriert. Der 'Befehl' ist das, was du immer in die Konsole eingibst. Das was die Konsole dann 'antwortet' also die Ausgabe wird auf die Webseite umgeleitet.
Die Datei cmd.txt und das Skript müssen sich im gleichen Verzeichnis befinden, dass es funktioniert. Hier ein Beispiel als Inhalt dieser Datei:
"/dies/ist/ein/Beispiel" "ls /etc"
Das würde bei Aufruf der URL http://raspberrypi/dies/ist/ein/Beispiel den Befehl ls /etc ausführen und die Ausgabe auf der geöffneten Seite anzeigen. Das setzt voraus, dass der Hostname des Raspis noch raspberrypi ist und keine statische IP festgelegt ist. Sonst muss die IP-Adresse oder der gesetzte Hostname eingegeben werden.
Das meiste an dem Skript sind allerdings die Debugginginformationen, die alle über die Website ausgegeben werden. Wenn also irgendetwas nicht stimmt, wird der Fehler nicht in der Konsole, sondern auf der Seite ausgegeben! Egal, ob die Datei cmd.txt nicht erstellt wurde, keinen gültigen Inhalt hat oder eine URL aufgerufen wird, für die kein Befehl hinterlegt ist.
Wenn du auch noch einen Cronjob mit dem Skript einstellst, musst du nur noch den Raspi an den Strom anschließen, um den HTTP-Server zu starten. Cronjobs kannst du über den Befehl crontab -e erstellen. An das Ende der Datei, die sich nach bestätigen dieses Befehls öffnet, schreibst du diese Zeile:
@reboot node /home/pi/http-control.js
Das setzt voraus, dass du das Skript http-control.js genannt hast und es im Homeverzeichnis des Benutzers pi liegt.
Ich hoffe, das Skript nutzt doch noch jemandem etwas, dass ich es nicht völlig umsonst geschrieben habe.
Liebe Grüße
Win7User
ouh ich habe vergessen, die URL aufzuschreiben, unter der die Seite erreichbar ist.
Hier ist sie:
http://hostname:8080/url/für/den/befehl
Also hostname ist der Hostname des Raspberry Pi. Den bekommst du über den Befehl sudo raspi-config > Hostname oder er ist raspberrypi, wenn du ihn nicht geändert hast. Die URLs für Befehle musst du selbst in der Datei cmd.txt festlegen. Aber das und wie sie aussehen müssen steht auch auf der Seite, wenn du drauf kommst und die Datei noch leer ist.
Moin Win7User.
Ich bin hier auf den schon etwas älteren Eintrag gestoßen.
Ich habe das Beispiel erfolgreich umgesetzt. Aber scheitere an meiner speziellen Anwendung.
Ich habe einen Pi 3 mit dem 7 Zoll Raspberry Display am laufen. Ich möchte auf dem Display einen Stream einer Kamera vor meiner Haustür darstellen. Ich habe auf meinem PI ein Bash script, das besagten Stream im omxplayer auf dem Raspberry öffnet. Ein zweites Script schließt den Stream wieder.
Per SSH kann ich diese Scripte bereits pronblemlos nutzen. Allerdings möchte ich diese Scripte per HTTP Request aus meiner Haussteuerung heraus starten. Wenn ich jetzt in der cmd.txt Datei im zweiten Teil den Befehl "sh videoan.sh" eintrage, bekomme ich die Fehlermeldung "Must be connected to a terminal".
Wie kann ich mein Problem lösen?
Haben Sie einen Tip für mich?
Freundlichst
Siebo
Webserver installieren z.B. den Apache oder NginX, eine Scriptsprache wie PHP installieren und dann ein PHP-Script schreiben das dein Shell-Script aufruft.
Mit URL meinst du doch sicherlich http://192.... bla bla, du musst somit einen Webserver zur Verfügung stellen, mit statischen Webseiten kannst du aber keine Ansteuerung machen, sowas geht nur mit Serverseitigen Scriptsprachen.
Ganz rudimentär
<?php exec('pfad/zum/script.sh'); ?>
Wie schreibe ich ein Php skript das mein shell aufruft?