carl7n
Goto Top

SSH Verbindung und Ausführen von Script via URL triggern

Hallo,

ich möchte folgendes realisieren:

Wenn ich eine bestimmte URL auf meinem Debian Webserver aufrufe, soll dieser sich per SSH mit meinem Mac verbinden und dort ein AppleScript ausführen.

Ich habe versucht, dies über ein Shell Script zu lösen. Das Script an sich funktioniert (Login per SSH, dann ENDSSH, dann osascript script.scpt). Allerdings kann ich es nicht über eine URL triggern. Genau dies ist aber wichtig. Ich möchte mit Llama auf meinem Android eben etwas automatisieren ("wenn verbunden mit Heimetzwerk, rufe URL auf" --> die URL triggert über Debian den Mac).

Der Umweg über Debian ist gewollt, denn ich habe vor, in Zukunft einen raspberry pi mit raspbian als Server laufen zu lassen. Hierüber sollen auch andere Automatisierungen stattfinden, sodass es mir nichts bringen würde, diesen Einzelfall direkt von Android nach Mac zu realisieren, selbst wenn das möglich wäre.

Ich bin ein ziemlicher Anfänger auf diesem Gebiet, daher bitte ich um Nachsicht. Vielleicht könnt Ihr mir ja weiterhelfen face-smile?

Danke & beste Grüße

Content-ID: 263347

Url: https://administrator.de/contentid/263347

Ausgedruckt am: 22.11.2024 um 12:11 Uhr

SlainteMhath
SlainteMhath 13.02.2015 um 15:28:48 Uhr
Goto Top
Moin,

also jetzt mal alle Sicherheitsaspekte aussen vor:

wenn du auf dem Debian eine PHP Seite packst, die ein
system("/pfad/zu/ssh -i /pfad/zum/private-key user@mac /pfad/zum/apple.script");  
macht sollte das eigentlich funbktionieren.

lg,
Slainte
carl7n
carl7n 13.02.2015 um 20:00:30 Uhr
Goto Top
Vielen Dank für den Tipp.

Ich konnte nicht herausfinden, in welchem Pfad ssh liegt.
Meine php sieht jetzt so aus
system ("ssh -i ~/.ssh user@192.168.189.2 ~/Desktop/Scripts/applescript.scpt");  
CHMOD 660 ist gesetzt. Es passiert nicht.

Ich habe noch folgendes probiert:
- dem Applescript "osascript" vorangestellt (so würde es im OSX Terminal gestartet werden); ohne Erfolg.
- das Ausführen des Scripts gegen einen einfacheren Befehl ausgetauscht --> [...| 192.168.189.2 say TEST"); ohne Erfolg.

Der PHP Server funktioniert definitiv, andere Scripte laufen (hatte ihn mir vorhin sowieso zerschossen und musste nun neu aufsetzen ^^).
Woran kann es liegen? Ist entweder die Location des ssh-Befehls falsch, oder aber kann PHP so gar kein SSH senden?

LG
Arano
Lösung Arano 14.02.2015 aktualisiert um 10:59:26 Uhr
Goto Top
Hi.

Das einezige was mir gerade auf die schnelle auffällt ist das "home"-Verzeichnis.
PHP wird von Apache ausgeführt und Apache läuft als welcher User, vermutlich www-data. und genau... dieser User hat kein Homeverzeichnis also auch keinen SSH-ID mit der er sich gegenüber anderen Identifizieren könnte. Evtl. (reine spekulation) benötigt der Parameter "-i" sogar auch einen Dateinamen und nciht nur den Pfad. Also scheitet es so schon bei der SSH Verbindung.

Ich habe da aber etwas anderes !
Ich selber habe hier auch ein RasPi "rumliegen" das unter anderem als Internetradio verwendet wird (mpd) und dessen Steuerung (play/stop/volume) habe ich über ein "Webinterface" eingerichtet bzw. über URL Aufrufe so wie du es im Grunde auch vor hast.

Mit xinetd binde ich ein Bash-Script an einen Port bzw. lasse Anfragen an diesen Port an das Script weiterleiten. Das Script wertet die Anfrage aus und ruft dan die gewünschte Funktion auf. Die wiederum kann alles was die Bash zu bieten hat.

# /etc/xinetd.d/"PORTSCRIPT" 
#
#    > ## default: off
#    > # description: An xinetd internal service which echo's characters back to  
#    > # clients.
#    > # This is the tcp version.
#    > service portscript
#    > {
#    >         socket_type = stream
#    >         protocol    = tcp
#    >         port        = 33000
#    >         type        = UNLISTED
#    >         wait        = no
#    >         user        = root
#    >         server      = /home/pi/portscript.sh
#    >         #server_args = Hallo Welts!
#    > }
Sehe gerade das das Script dann mit ROOT-Rechten läuft... das sollte man vieleicht auf "pi" abändern.

Und im BASH-Script dan etwa wie folgt: (She-Bang nicht vergessen)
# lese komando ein
read command
echo "Read: $command" >>$LOG  



# zerlege $command anhand der leerzeichen in "brocken" 
# $1 = hauptCommand
# $2 = parameter 1
# $3 = para2 , ...
IFS=" "  
set -- $command


# fuere aktion zu $command aus
case $1 in

    test)
        echo "TEST"  
        ;;

    play)
        exe "$command"  
        mpc play >>$LOG 2>&1
        ret=$?; [ $ret -ne 0 ] && err "002" "Komando meldet Fehlercode $ret" "$ret"  
        ;;

    *)
        err "001" "Server kennt Komando \"$command\" nicht" "1"  
        ;;
esac

Aufrufen tue ich das ganze dann allerdings über eine selbsterstellte Android-App mit der ich nun in Wlan reichweite meinen Musik steuern kann.
Die GPIOs können so auch angesprochen werden... wollte diese verwenden um meinen Verstärker ein und aus schalten zu können... das ist mir aber noch nicht geglückt face-sad Dauerbetrieb das Verstärkers ist ja auch doof


Was mir nur bis jetzt noch nicht eingefallen war, war die automatisierung mittels Llama (das ich bereits in verwendung habe) um die Wiedergabe zu starten wenn ich nach hause komme / stoppen beim verlassen.
Dafür danke ich dir ! face-smile

Achso, gerichtet habe ich mich damals nach diesem Artikeln: http://www.debian-administration.org/article/371/A_web_server_in_a_shel ...


~Arano
carl7n
carl7n 14.02.2015 um 11:37:13 Uhr
Goto Top
Vielen Dank für das Bereitstellen des Scripts face-smile Kannst Du mir noch ein paar Informationen geben?

Ich habe einen apache2 Webserver laufen. Gibt es in Zusammenhang mit xinetd Probleme? service start xinetd gibt die Meldung "[FAIL] Starting internet superserver: xinetd failed!".

  1. /etc/xinetd.d/"PORTSCRIPT" habe ich unverändert angelegt. Ich glaube, dass ich es per root laufen lassen muss, da die ssh-keys zur Authentifizierung auf dem Mac (damit keine Passworteingabe erfolgen muss) nur für root gelten.

Wie lege ich nun das Bash Script meinen Vorgaben entsprechend an? Da ich wirklich blutiger Anfänger bin, sieht das für mich ziemlich verwirrend aus. Sehe ich das richtig, dass zwischen ) und ;; jeweils komplette Bash Scripts stehen können? Also beispielsweise
on)
ssh user@mac <<'ENDSSH'  
osascript ~/Scripts/mediaon.scpt
;;

off)
ssh user@mac <<'ENDSSH'  
osascript ~/Scripts/mediaoff.scpt
;;
etc.?
Bzw. direkt in die erste Zeile nach KlammerZu jeweils den Shebang?

Eine selbsterstellte Android-App kommt aufgrund meines derzeitigen Kenntnisstands nicht in Frage. Ist es leicht realisierbar, einfach verschiedene Ports festzulegen und diese per Browser anzusteuern? Beispiel:
Media On Port 33000
Media Off Port 33001
Mute Port 33002
usw.

Dies möchte ich einfach über den Browser triggern, sofern möglich. Also wenn ich z.B. in Android raspiserver:33001 (per Llama) im Browser aufrufen lassen, soll das Media Off Script gestartet werden.
Oder werden die Befehle einfach angehängt? Also raspiserver:33000?on, raspiserver:33000?off, raspiserver:33000?whatever?

Für mich ist es wichtig, dass ich direkt per Browser Befehle triggern kann. Das ist für mich die naheliegendste Möglichkeit, alles per Llama automatisieren zu können. Quasi so: bei Einlesen von NFC Tag "X" App-Schnellzugriff Lesenzeichen "X" (also z.B. raspiserver:33000?befehl) ausführen.
Arano
Arano 14.02.2015 um 15:11:50 Uhr
Goto Top
Hi,

das wird wohl doch schwerer als gedacht...

Nein, mit dem Apache sollte das keine Probleme geben !
Wegen den SSH-Keys die nur für root gelten, das könnte man auch ändern/anpassen aber das lassen wir jetzt mal lieber.
Wegen dem Script, das ganze ist EIN Bash-Script und wegen der Frage wo die She-Bang hin soll, müsste jetzt ein Bash-Grundkurs folgen. Um diesen muss du dich aber selber kümmern wenn du auf diesem Weg bleiben möchtest (ich kenne aber auch keinen anderen).

Mein Script ist da noch ein Stück komplexer und ich habe nur die relevanten Teile gepostet die du dann selber zusammensetzen solltest. Die She-Bang stellt dabei die erste Zeile in der Datei dar, damit beim ausführen das Betriebssystem erkennen kann um was für ein Script es sich handelt. Könnte ja auch ein Sh-Script oder ein Perl-Script oder PHP, oder viele andere sein. Anschließend wird der Dateiinhalt an das entsprechende Programm/Interpreter weitergegeben und dieser interpretiert es / arbeitet es ab. Hier wäre /bin/bash der passende Interpreter / die auszuführende Datei und die She-Bang dazu: "#!/bin/bash"

Wie gesagt, Bash-Grundkurs möchte ich hier nicht geben:
  1. Weil ich mich dafür nicht als geeignet sehe (Ich kann zwar vieles aber eben nicht alles und wenn man lehr, dann richtig oder gar nicht !)
  2. gibts davon schon viele und
  3. um eigene Erfahrung kommt man nun mal nicht herrum

Möglicherweise ist das ganze so auch viel zu komplex für dich, denn der Browser sendet ja auch nicht nur einfach den "Befehl" der generiert einen kompletten HTTP-Header (denn das ist ja seine Aufgabe als Browser). Darum auch der Link zum Ende des Posts, dort habe ich ja auch abgeschaut.
s. Step 2+3
In Step 3 verwenden wir den Dateinamen dann als Schlüsselwort um unsere gewünschten Aktionen ausführen zu lassen. filename = command

Und anstelle von Step 4 (auslieferung der Datei) erfolgt dann unsere definition der Aktionen - in meinem Script das CASE.
Je nach Schlüselwort/Befehl/Command wird dann NUR ein anderer Teil des Scripts aufgeführt (play/pause/volume,ect.)
Und ja, hier hast du das richtig erkannt, zwischen ) und ;; stehen dann weitere Bash-Komandos.

Wie du ds ganze dann zusammenstellst bleibt dir überlassen, allerdings alles an einzelne Ports zu hängen tu absolut nicht not ! Dann müsstest du für jeden Befehl ein Port belegen, ein xinetd-Anweisung erstellen und je ein separates Script erstellen.
ODER man Schreibt ein Script, das je nach Befehl etwas anders macht und hängt es an einen einzigen Port. Das ist auch viel einfacher erweiterbar, einfach das Script erweitern und das wars.


  • Willst du hier überhaupt weitermachen ?


Wenn ja dann fang doch klein an.
Lasse das Script doch einfach nur die Zeit in eine Datei schreiben, dann kannst du das Triggern per Browser testen. Und wenn das funktioniert, dann wird halt erweitert: HTTP-Header auslesen, auseinandernehmen, Schlüsselwort suchen, je nach Schlüsselwort etwas anders in die Datei schreiben und zu letzt das ausführen der Aktionen.
Zum entwicklen ruhig immer in zwischenschritten etwas in die Datei mit hinein schreiben, dann kann man ganz gut mitverfolgen wie weit das Script gekommen ist bis es "nicht mehr weitere ging" und hat so einen anhalspunkt an dem man nach einem Fehler suchen kann.

Solange xinetd aber mit einer Fehlmeldung restartet (bzw. NICHT startet), macht das ganz sicherlich keinen Sinn !
Mit netstat kannst du schauen ob, NACHDEM xinetd OHNE Fehler startet, ob der Port belegt ist:
pi@raspberrypi /etc/xinetd.d $ sudo netstat -tapen | grep 33000
tcp        0      0 0.0.0.0:33000            0.0.0.0:*               LISTEN      0          61020       6778/xinetd     
pi@raspberrypi /etc/xinetd.d $

Mein Anweisung für xinetd sieht wie folgt aus:
pi@raspberrypi /etc/xinetd.d $ cat portscript 
# default: off
# description: An xinetd internal service which echo's characters back to 
# clients.
# This is the tcp version.
service portscript
{
        socket_type = stream
        protocol    = tcp
        port        = 33000
        type        = UNLISTED
        wait        = no
        user        = root
        server      = /home/pi/portscript/script.sh
        #server_args = Hallo Welts! 
}
pi@raspberrypi /etc/xinetd.d $


~Arano


Ich probiere gerade mein Script unter "pi" laufen zu lassen aber schainbar ist mein internetradiostream gerade... "lautlos" *fg* Verbunden wird zwar und es wird wiedergegeben... aber ich höre nichts !? Naja, mal schaun.
carl7n
carl7n 14.02.2015 um 18:34:21 Uhr
Goto Top
Ich habe mich mal ein bisschen eingelesen und verstehe nun ein wenig mehr. Hoffe ich jedenfalls ^^ Ich gebe mal möglichst viele Details, damit eventuelle Fehler schneller gefunden werden können.

/home/raspi/portscript.sh
#!/bin/bash
#Kommando auslesen
read command
echo "Read: $command" >>$LOG  

#Zerlege $command anhand der Leerzeichen in "Brocken" 
# $1 = hauptKommando
# $2 = Parameter 1
# $3 = Parameter 2 
# etc.
IFS=" "  
set -- $command

#Fuehre Aktion zu $command aus
case $1 in

        test)
                #!/bin/bash
                echo "TEST"  
                ;;

        file)
                #!/bin/bash
                date >> portscripttest.txt
                ;;

        *)      #!/bin/bash
                err "001" "Server kennt Kommando \"$command\" nicht" "1"  
                ;;
esac
chmopd +x portscript.sh

/etc/xinetd.d/portscript
  GNU nano 2.2.6                                 Datei: portscript                                                                          

service portscript
{
        socket_type     = stream
        protocol        = tcp
        port            = 33000
        type            = UNLISTED
        wait            = no
        user            = root
        server          = /home/raspi/portscript.sh
        #server_args    = Hallo Welts!
}

netstat
root@RaspberryPi:/etc/xinetd.d# sudo netstat -tapen | grep 33000 
tcp        0      0 0.0.0.0:33000           0.0.0.0:*               LISTEN      0          24123       6267/xinetd     
root@RaspberryPi:/etc/xinetd.d# 

Öffne ich nun localhost:33000 im Browser wird für den Bruchteil einer Sekunde etwas angezeigt, danach versucht mein Browser, mich an www.localhost.com:33000 weiterzuleiten. Fehlermeldungen:
/home/raspi/portscript.sh: Zeile 5: $LOG Mehrdeutige Umlenkung
/home/raspi/portscript.sh: Zeile 32: err: Kommando nicht gefunden.

Wie kann ich nun mithilfe der URL den Befehl Test oder file anhängen? Ich habe es mit locahost:33000?test, locahost:33000/test und localhost:33000-test versucht, ohne Erfolg. Stimmt etwas mit meiner portscript.sh nicht?
Arano
Arano 14.02.2015 um 20:53:25 Uhr
Goto Top
Hi,

Stimmt etwas mit meiner portscript.sh nicht?
Na sicher stimmt damit etwas nicht !
Den schließlich bekommst du FEHLERmeldungen...

/home/raspi/portscript.sh: Zeile 5: $LOG Mehrdeutige Umlenkung
echo "Read: $command" >>$LOG  
Die Variable $LOG ist nicht definiert, deswegen gibt es kein Umleitungsziel und das erzeugt den Fehler. $LOG sollte den Pfad und Dateinamen der gewünschten Logdatei enthalten.

/home/raspi/portscript.sh: Zeile 32: err: Kommando nicht gefunden.
        err "001" "Server kennt Kommando \"$command\" nicht" "1"   
"err" ist eine Funktion die ich in meinem Script erstellt habe. Sie bekommt drei Parameter und ist dann für ein gewisses Maß an Logging, Fehlerbehandung und Rückgabewert (für meine App) verantwortlich.

Ich sag doch, fange klein an !


~Arano
carl7n
carl7n 14.02.2015 aktualisiert um 21:58:15 Uhr
Goto Top
Weiter gehts...

In xinetd.d habe ich "test" angelegt. Gleicher Inhalt, nur anderer Port und andere .sh .

/home/raspi/test.sh
#!/bin/bash
#Kommando auslesen
read command
date >> /home/raspi/triggertest/log.log
 echo "Kommando: $command" >> /home/raspi/triggertest/log.log  

#Kommandos aufteilen
# $1 Hauptkommando
# $2 Parameter1
# $3 Parameter2 etc.

set -- $command

#Aktion in $command ausfuehren
case $1 in

	/1)
		#!/bin/bash
		echo "TEST"  
		;;

	/2)
		#!/bin/bash
		xmessage -center HI there.
		;;

esac

case $2 in

	/3)
		#!/bin/bash
		date >> /home/raspi/triggertest/run.log
		;;

	/4)	#!/bin/bash
		ssh user@192.168.189.12 <<'ENDSSH'  
                osascript ~/scripts/runme.scpt
		;;

esac

Änderungen: das Logfile ist suboptimal, da Datum und Kommando in verschiedene Zeilen geschrieben werden. Damit kann ich leben, hatte das eh nur testweise erstellt. Das Aufteilen der Commands habe ich herausgenommen, weil es für mich eh nicht funktioniert hat (egal was ich hinter 127.0.0.1:33000 geschrieben habe, die Befehle wurden nicht akzeptiert).

So wie es jetzt ist, funktioniert es zumindest bedingt. Also localhost:45000/1 triggert in diesem Fall tatsächlich /1). So weit, so gut. /1), /2) und /4) funktionieren allerdings nicht.
/3) läuft allerdings problemlos, die Datum und Uhrzeit werden in der angegebenen Datei gespeichert.

Grundsätzlich funktioniert nun also das Triggern per Webinterface. Allerdings lässt sich genau das, was der Hauptgrund für diese Prozedur war, nicht umsetzen. Nämlich per SSH ein applescript auf meinem Mac ausführen. Das Script unter /4) habe ich auch als eigenstände .sh. Wenn ich diese über das Terminal ausführe, funktioniert sie. Ich werde jetzt mal probieren, statt den Inhalt der .sh unter /4) zu schreiben einfach die .sh ausführen zu lassen... Vielleicht funktioniert das ja.

Im Browser erscheint nach dem Bruchteil einer Sekunde immer wieder
Fehler: Verbindung unterbrochen
Die Verbindung zum Server wurde zurückgesetzt, während die Seite geladen wurde.

Auf die Befehle hat dies aber keinen Einfluss, sie funktionieren trotzdem.

EDIT: ja, wenn ich statt den Befehlen einfach die sh ausführen lasse, läuft alles face-smile Vielen Dank für die Hilfe. Es besteht sicher noch Optimierungsbedarf, aber ich fange ja auch gerade erst an, mich in die Marterie einzuarbeiten.
carl7n
carl7n 15.02.2015 um 08:14:03 Uhr
Goto Top
Da sich nun per Webinterface Befehle ausführen lassen, würde ich gerne noch etwas finetunen.

Aus irgend einem für mich nicht nachvollziehbaren Grund funktionieren in diesem Script erst Befehle _nach_ "case $2 in". Würde ich den Inhalt von /3) in /1) oder /2) kopieren und aufrufen, würde gar nichts passieren.

Dabei sind doch beide Blöcke exakt gleich aufgebaut.
case x in
command1
command2
usw.
esac

Was mich noch stört, ist die Ausgabe auf dem Webinterface bzw. die Weiterleitung. Unter Android versucht Chrome, die Seite wieder und wieder zu laden, was zu mehrfachem Triggern der Befehle führt. Dies passiert auf dem Rechner nicht, aber kurze Fehlermeldung, dann Seitenladefehler finde ich trotzdem nicht so toll gelöst.

Ich werde einfach mal weiter am Script arbeiten, bin aber parallel auch für jeden Lösungsansatz dankbar face-smile
carl7n
carl7n 15.02.2015 aktualisiert um 18:54:52 Uhr
Goto Top
Edit: Problem gelöst. Die commands werden nun per tcp über ein php-Script direkt an den Port weitergeleitet und werden korrekt ausgeführt.
Arano
Lösung Arano 16.02.2015, aktualisiert am 17.02.2015 um 20:53:55 Uhr
Goto Top
Hallo

Ach her je... wo soll ich da nur anfangen ...will ich das überhaupt !?

Ich kann es nur wiederholen: Fange klein an und schau was passiert !
Das die Hälfte nicht funktioniert ist bei dem Script kein Wunder !

da Datum und Kommando in verschiedene Zeilen geschrieben werden
Jup, du hast es ja auch so geschrieben. Mit zwei separaten Kommandos.
echo "`date` Kommando: $command" >> $LOG

Also localhost:45000/1 triggert in diesem Fall tatsächlich /1). So weit, so gut. /1), /2) und /4) funktionieren allerdings nicht.
Hä ? Wird "/1" nun getriggert oder nicht !?
Ich weis schon warum nicht

Grundsätzlich funktioniert nun also das Triggern per Webinterface.
Wie jetzt, eben hast du doch gesagt das 75% NICHT funktionieren !?

Wenn ich diese (extra Script) über das Terminal ausführe, funktioniert sie.
Ja klar, aber dann läuft es auch in deiner User-Umgebung. Wenn es unter xinetd läuft ist es eine andere Umgebung bzw. wohl die vom User root. Es wird also von ganz anderen Standpunkten ausgegangen. Wenn nicht sogar die Login-Session eine weitere Rolle dabei spielt !?

Im Browser erscheint nach dem Bruchteil einer Sekunde immer wieder
Fehler: Verbindung unterbrochen
Die Verbindung zum Server wurde zurückgesetzt, während die Seite geladen wurde.
Jup... dazu hatte ich auch schon erwähnt, das eine Browser einen vollständingen HTTP-Request sendet ! Bei mir sind es insgesamt ACHT ZEILEN und die wollen ausgelesen werden.
GET /kommando HTTP/1.1
Host: localhost:33000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
                              <--  eine leerzeile !!!
Was meinst du warum ich die ganze Zeit davon spreche klein anzufangen und Schritt für Schritt vorzugehen, mit dem Hinweis sich Dinge anzeigen zu lassen !? Dan hättest du zumindes gesehen, das in der Variable die komplette GET-Zeile steht.

Aus irgend einem für mich nicht nachvollziehbaren Grund funktionieren in diesem Script erst Befehle _nach_ "case $2 in". Würde ich den Inhalt von /3) in /1) oder /2) kopieren und aufrufen, würde gar nichts passieren.
Für mich ganz verständlich und sorry, aber ich muss wieder auf die erste GET-Zeile verweisen.
Mit dem Zusatz von set -- $command wird (um es einfach zu halten) der Inhalt von $command anhand der Leerzeichen getrennt und auf $1,$2,$3,$... -$9 aufgeteilt.
Darum Funktionieren nur die Abschnitte in dem zweitem CASE weil hier die Variable "$2" (die den Pfad bzw. den Befehl beinhaltet) ausgewertet wird. Darum funktionieren auch nur die Abschnitte /3 und /4.
GET /kommando HTTP/1.1
$1  $2    $3

Was mich noch stört, ist die Ausgabe auf dem Webinterface bzw. die Weiterleitung. Unter Android versucht Chrome, die Seite wieder und wieder zu laden, was zu mehrfachem Triggern der Befehle führt. Dies passiert auf dem Rechner nicht, aber kurze Fehlermeldung, dann Seitenladefehler finde ich trotzdem nicht so toll gelöst.
Nun, du verwendest ja auch einen Browser der für HTTP-Request geschaffen wurde. Wenn man den zweckentfremden möchte, muss man sich halt an seine Regeln halten.
s. Step 2 aus dem Link
Und ja richtig, in meinem Script taucht dieser Part nicht auf. Aber ich sagte ja auch bereits, das ich das anders handhabe. Denn ich verarbeite nicht den HTTP-Request, ich habe mir meinen eigenen Request konstruiert um mehrere Informateionen übertragen zu können da ich das mit meiner App triggere (Die Webversion war nur der Anfang)

Edit: Problem gelöst. Die commands werden nun per tcp über ein php-Script direkt an den Port weitergeleitet und werden korrekt ausgeführt.
Öhm... das verstehe ich nicht !?
Naja, wie auch immer, da das Script noch so enige Macken hat fält es mir schwer zu glauben das es so "korrekt" funktioniert...
Ich vermute mal, das du nur die Fehler nicht siehst und deswegen glaubst alles sei in Ordnung. (Nun, das geht aber wohl jedem Anfänger so - Mann will ein Ergebniss, alles andere ist egal face-smile )


Ich habe noch ein Backup meiner Webversion gefunden:
(Funktioniert auch mit dem Smartphone Standardbrowser einwandfrei)
#!/bin/bash



##
## Browser sendet vollständigen Request:
##
#
#   > GET /kommando HTTP/1.1
#   > Host: localhost:31313
#   > User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0
#   > Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
#   > Accept-Language: de-de,en-us;q=0.7,en;q=0.3
#   > Accept-Encoding: gzip, deflate
#   > Connection: keep-alive
#   >                              <--  eine leerzeile !!!
#




# lese die erste Headerzeile des Browserrequests
read request
# $request = "GET /kommando HTTP/1.1"  


# lese die restlichen Headerzeilen aus der Eingabe
while /bin/true; do
    read header
    # wenn Leerzeile erreicht sind alle Header ausgelesen
    [ "$header" == $'\r' ] && break;  
done


# extrahiere den Pfad aus dem Request
command="${request#GET /}"       # "kommando HTTP/1.1"  
command="${command% HTTP*}"      # "kommando"  




# führe aktion je nach Anfrage durch
case $command in
    
    a)
        echo "aaaa"  
        ;;
    
    b)
        echo "bbbb"  
        ;;
    
    1)
        echo "1111"  
        ;;
    
    2)
        echo "2222"  
        ;;
    
    3)
        echo "3333"  
        ;;
    
    4)
        echo "4444"  
        ;;
    
    *)
        echo "default  
                Das Triggern erfolgt durch einen Browserrequest:
                    http://localhost:33000/KOMMANDO
                    
                Es gibt die folgenden KoMmandos:
                    a    =    http://localhost:33000/a
                    b    =    http://localhost:33000/b
                    1    =    http://localhost:33000/1
                    2    =    http://localhost:33000/2
                    3    =    http://localhost:33000/3
                    4    =    http://localhost:33000/4
                Jedes andere Kommando zeigt diese default-Ausgabe."  
        ;;
    
esac




# ENDE
exit 0
carl7n
carl7n 17.02.2015 aktualisiert um 14:59:07 Uhr
Goto Top
Zitat von @Arano:
> da Datum und Kommando in verschiedene Zeilen geschrieben werden
Jup, du hast es ja auch so geschrieben. Mit zwei separaten Kommandos.
echo "`date` Kommando: $command" >> $LOG
Naja, ich bin halt noch Anfänger auf dem Gebiet. Ich hatte das zwischenzeitlich so gelöst:
echo -n $(date +%a) $(date +%R:%S) >> /home/raspi/scripts/logs/webtrigger.log
echo " Kommando: $command" >> /home/raspi/scripts/logs/webtrigger.log;  
Übersichtlicheres Datum + das Kommando in derselben Zeile.


Hä ? Wird "/1" nun getriggert oder nicht !?
Ich weis schon warum nicht

Ich hatte mich verschrieben. 1,2 und 4 werden nicht getriggert, ausschließlich 3. Ist jetzt in Retrospektive ein bisschen schwer nachzuvollziehen, da ich das Script mittlerweile ein wenig abgeändert habe. Wie gesagt, das Script unter 4 wird nun nicht mehr direkt eingefügt, sondern per sh /home/raspi/scripts/script.sh aufgerufen. So läuft es.


Dan hättest du zumindes gesehen, das in der Variable die komplette GET-Zeile steht.
Japp. Mit ist das im Logfile aufgefallen und ich habe erstmal gerätselt, warum das so ist. Das Extra-Script, welches das Command an dieses Script weiterleitet, sendet einen "reinen" Befehl, also statt "GET /kommando HTTP/1.1" wirklich nur "kommando". Scheint ja aber eigentlich unnötig zu sein, wenn ich die port.sh richtig anpasse.


Wie jetzt, eben hast du doch gesagt das 75% NICHT funktionieren !?
Das habe ich umgangen, indem ich $1 komplett "übersprungen" habe (also keine Befehle dort eingetragen) und stattdessen bei $2 angefangen. Ist allerdings tatsächlich unschön und ich hätte lieber ein sauberes Script, damit ich un Zukunft auch alles weiterhin richtig mache.


Naja, wie auch immer, da das Script noch so enige Macken hat fält es mir schwer zu glauben das es so > "korrekt" funktioniert...
Ich vermute mal, das du nur die Fehler nicht siehst und deswegen glaubst alles sei in Ordnung. (Nun, das > geht aber wohl jedem Anfänger so - Mann will ein Ergebniss, alles andere ist egal )

Ich versuche das mal (mit meinem Anfängerwissen) zu erklären. Anstatt localhost:port?command aufzurufen, rufe ich localhost/phptrigger?command auf. phptrigger.php schickt das Kommando per Telnet an localhost:port. So fällt der GET / HTTP etc. weg, es wird ein reiner Befehl geschickt.
Vorher stand im Log sowas wie "So 19:43:16 Kommando: GET /test HTTP/1.1", mittlerweile "Tue 08:22:54 Kommando: get /test". Das "get /test" schickt phptrigger.php mit (weil ich die port.sh noch nicht dementsprechend angepasst habe und sie den Befehl daher ohne get / nicht erkennt). Das wollte ich jetzt eigentlich abändern, werde aber vorher mal Deinen neuen Ansatz ausprobieren und sehen, wie das dann bei mir läuft.

Grundsätzlich möchte ich aber schon 'anständig' coden und das von der Pieke an richtig machne. Dass das Script nun läuft, aber offensichtlich nicht gut gelöst ist, wurmt mich schon. Du sprichst immer von klein anfangen. Dein Script scheint ja mit mehreren Kommandos bzw. Werten zu arbeiten. Das ist für mich als schwerer zu durchschauen, da Du beispielsweise "Kommando Screen Wert Off" senden wüdest, ich aber einfach "Kommanda screenoff" bzw. "Kommando screenon". Natürlich ist Deine Lösung besser. Ich könnte Sachen wie "Kommando volume Wert x" senden, statt 100 Zeilen a lá "Kommanda volumeX" zu schreiben. (Oder? In der weiter oben geposteten Datei schien das so zu sein, in dieser Version ist es nicht so, sehe ich das richtig?)
Nochmal, ich bin blutiger Anfänger und muss mir diese Sachen verständlich machen, bevor ich sie durchschaue. Ich habe keinerlei Programmierkenntnisse und lerne praktisch durch copy-modify-paste. Schritt für Schritt lernt man so auch viel dazu.

Ich werde jetzt Deine Webversion implementieren und anpassen, dann noch ein Feedback abgeben. Erst einmal Danke für die Hilfe und vor Allem auch Geduld ^^

EDIT: Ich kann mich weiterhin nicht per SSH über dieses Script mit meinem Mac verbinden. Testscript

ssh user@192.178.189.12 <<'ENDSSH'
say "This is a test"

--> /home/raspi/p3.sh: Zeile 110: Warnung: here-document at line 54 delimited by end-of-file (wanted `ENDSSH')
/home/raspi/p3.sh: Zeile 111: Syntax Fehler: Unerwartetes Dateiende.
Ich habe den Fehler jetzt mehrmals gegoogelt, aber nichts gefunden, was mir weiterhilft. Da steht "wanted `ENDSSH'" statt 'ENDSSH', aber jede andere Schreibweise gibt den gleichen Fehler aus.

Der Rest funktioniert prima.
carl7n
carl7n 17.02.2015 aktualisiert um 19:43:41 Uhr
Goto Top
Okay. Offensichtlich war die Lösung
ssh user@ip<<ENDSSH
befehl
ENDSSH
Quatsch.

Stattdessen löse ich es nun per
ssh - n user@IP
befehl
Arano
Lösung Arano 17.02.2015 aktualisiert um 20:53:42 Uhr
Goto Top
Nabend

Ich habe den Fehler jetzt mehrmals gegoogelt, aber nichts gefunden, was mir weiterhilft. Da steht "wanted `ENDSSH'" statt 'ENDSSH', aber jede andere Schreibweise gibt den gleichen Fehler aus.
Mit der HereDoc-Notation bei SSH kenne ich nicht aus, das habe ich noch nie verwendet.

Dann lädt und lädt und lädt die Seite, nichts passiert.
Jup, das kann ich erklären.
Nach dem erfolgreichen SSH-Login befindest du dich auf der remote-box. Das Scriopt wird aber local ausgeführt: Schritt für Schritt. Das heist das dein locales Script erst auf die beendigung des letzten Befehls (SSH) wartet bevor es mit dem Nächstem weiter macht. Mit anderen Worten die SSH Verbindung muss erst beendet werden damit das Script weiterläuft.

Um es gerade mal auf den Punkt zu bringen, du verwendest die ganze Zeit ein fehlerhaftes SSH-Kommando (s. man ssh)
Funktionieren könnte:
ssh user@ip 'osascript ~/scripts/runme.scpt'  
Übergebe SSH das was du remote ausführen willst als einen Parameter.


~Arano
carl7n
carl7n 17.02.2015 um 19:57:55 Uhr
Goto Top
Also wie es aussieht, funktioniert nun alles. Zumindest habe ich bislang keine Fehler erlebt. Das Script gibt aus, was es soll. Keine Timeouts, alles bestens.
Ich bedanke mich recht herzlich! Habe hierdurch schon viel gelernt und freue mich auf weitere Projekte.