Mixer
Anmeldungsdatum: 2. Februar 2008
Beiträge: 153
Wohnort: Bayern
|
Hallo, ich möchte gerade eine kleine Web-Anwendung mit lighttpd schreiben. Wenn ich mit einem Shell-Skript eine Webseite erzeuge, dann geht das auch problemlos, also z.B.: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | #!/bin/sh
cat << EOF
Content-Type: text/html
<html>
<head>
<title>cgi shell scripting example</title>
</head>
<body>
<h1>Stats for this computer</h1>
EOF
echo Date: $(date) "<br />"
echo Uptime: $(uptime) "<br />"
cat << EOF
</body>
</html>
EOF
|
Jetzt habe ich eine html-Seite geschrieben wo ich mit <form> ein anderes CGI-Skript aufrufe, dass dann nur einen Befehl ausführen soll. Die Seite im Browser sollte sich nicht ändern. Der HTML-Aufruf sieht so aus: | <form action="/cgi-bin/driver_led_off.sh" method="post">
<input type="submit" value="Switch off LED Driver"></form>
|
Hier erscheint der Fehler 500.
Ein anderer Aufruf sieht so aus: | <form action="/cgi-bin/driver_led_off.sh" method="post">
<input type="button" name="OFF" value="Switch off LED Driver"></form>
|
Hier passiert anscheinend gar nichts. Der Befehl wird in beiden Fällen nicht ausgeführt! Und das CGI-Skript was die Arbeit verrichten soll so: | #!/bin/sh
i2cset -y 0 0x60 0x00 0x11
echo "HTTP/1.0 204 No Change"
|
Das CGI-Skript ist ausführbar und gehört dem richtigen Benutzer. Hat jemand eine Ahnung was ich wo falsch mache?? Wenn jemand Ahnung von einer Parameterübergabe in das Skript hat (mir würde einer reichen) wäre das auch noch hilfreich!! Danke schon mal im Voraus Mixer
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Mixer schrieb: Hat jemand eine Ahnung was ich wo falsch mache??
Ja, Du verwendest Bash und CGI 😛 Du solltest im Log des Servers den genauen Fehler sehen! Und wenn Du ihn nicht erkennst, solltest Du den relevanten Inhalt hier posten. Ich vermute mal stark, dass Dein Script Ausgaben nach Standardout macht. Das dürfte zum 500er führen.
|
Mixer
(Themenstarter)
Anmeldungsdatum: 2. Februar 2008
Beiträge: 153
Wohnort: Bayern
|
Hallo, komme leider nicht drum herum - perl läuft irgendwie gar nicht... Im error.log stehen keine Fehlermeldungen. Wenn ich per "submit" übermittle wird das Skript jetzt ausgeführt, mit "button" geht es nicht. Allerdings kommt hald dann die Seite mit dem Fehler, und dann sollte eigentlich wieder die aufrufende html-Seite kommen. Wie komme ich da wieder zurück?? Gruss
Mixer
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Mixer schrieb: komme leider nicht drum herum - perl läuft irgendwie gar nicht...
Naja, gibt ja zig tausend Möglichkeiten - da ist Perl ja nur eine (nicht unbedingt gute).
Im error.log stehen keine Fehlermeldungen.
Kann nicht sein! Gibt es ggf. ein spezielles log für CGI? Bzw. für dein Script? Ein 500er ist nun einmal ein Internal Server Error. Der muss protokolliert werden. Ich bin kein LightHTTPD Spezialist, aber da musst Du als allererstes mal fündig werden und ggf. Deine Konfiguration überarbeiten.
Wenn ich per "submit" übermittle wird das Skript jetzt ausgeführt, mit "button" geht es nicht.
Submit ist ja auch richtig.
Allerdings kommt hald dann die Seite mit dem Fehler, und dann sollte eigentlich wieder die aufrufende html-Seite kommen. Wie komme ich da wieder zurück??
Naja, ohne genauere Infos aus dem Log kommen wir da nicht weiter.
|
Mixer
(Themenstarter)
Anmeldungsdatum: 2. Februar 2008
Beiträge: 153
Wohnort: Bayern
|
Hallo, im error.log steht wirklich nix ausser dass der server gestartet wird. im access.log steht folgendes: | 169.254.7.1 169.254.7.7 - [20/Jan/1964:15:24:22 -0700] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.04 (lucid) Firefox/3.6.17"
169.254.7.1 169.254.7.7 - [20/Jan/1964:15:24:28 -0700] "POST /cgi-bin/driver_led_off.sh HTTP/1.1" 500 369 "http://169.254.7.7/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.04 (lucid) Firefox/3.6.17"
|
Weiss nicht ob das weiterhilft. Gruss P.S. Das Datum auf dem Server passt nicht, ist aber vorerst mal egal
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Sonderbar. Schreibt Dein Script denn etwas auf STDOUT?
|
Mixer
(Themenstarter)
Anmeldungsdatum: 2. Februar 2008
Beiträge: 153
Wohnort: Bayern
|
Nein, das Skript sieht mittlerweile so aus: | #!/bin/sh
i2cset -y 0 0x60 0x00 0x11
|
Also nur ein Utility-Aufruf
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Mixer schrieb: Nein, das Skript sieht mittlerweile so aus: | #!/bin/sh
i2cset -y 0 0x60 0x00 0x11
|
Also nur ein Utility-Aufruf
Ja und? ich kenne das Programm i2cset nicht und kann daher ja nicht wissen, ob das irgend welche Ausgaben tätigt. Dann gib doch einfach mal einen kleinen Testtext zurück, damit man sieht, ob das ganze erfolgreich durcläuft. Ggf. liegt es an Deinem "Referer"-Code.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6488
Wohnort: Hamburg
|
Ja, Du verwendest Bash und CGI 😛
Was ist daran so lustig? Ich mache das auch manchmal, mit Lighttpd allerdings nur zum testen. Auf meinem Fileserver benutze ich allerdings ein Notfallsystem auf einem 4GB Flashmodul mit bozohttpd als Server und der kann nunmal nur CGI und Perl ist für einfache Aufgaben schon fast ein Overkill... Jetzt habe ich eine html-Seite geschrieben wo ich mit <form> ein anderes CGI-Skript aufrufe, dass dann nur einen Befehl ausführen soll.
Das habe ich jetzt nicht wirklich verstanden, oder du hast dich etwas ungeschickt ausgedrückt. Jedenfalls rufst du mit einem <form> kein Script oder sonstwas auf; du sendest Daten an den Server zurück, und dieser soll dann damit etwas anfangen, falls er entsprechend programmiert wurde.
Die Seite im Browser sollte sich nicht ändern.
Das ist jetzt aber schon der zweite Schritt. Dazu möchte ich jetzt nichts sagen, da ich dazu selber erstmal etwas nachlesen muss. Jedenfalls benötigst du dazu Javascript um Inhalte einer bestehenden Seite zu aktualisieren (wird auch als Web 2.0 / Ajax verkauft). Du solltest die erstmal die Parameterübergabe, sprich Kommunikation zwischen Server und Script ansehen. Dazu empfehle ich mal folgendes ebenso primitives wie aufschlussreches Script auf dem Server als CGI zu starten (env.cgi):
#!/bin/bash
echo "Content-type: text/plain"
echo ""
env
echo
Wenn ich das dann mit http://silo.lan/cgi/env.cgi aufrufe kommt folgende Antwort: HTTP_KEEP_ALIVE=115
HTTP_USER_AGENT=Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.17) Gecko/20110422 Ubuntu/8.04 (hardy) Firefox/3.6.17
HTTP_HOST=silo.lan
SERVER_PORT=80
HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
DOCUMENT_ROOT=/home/www/silo.lan/html/
SCRIPT_FILENAME=/home/www/silo.lan/html/cgi/env.cgi
REQUEST_URI=/cgi/env.cgi
SCRIPT_NAME=/cgi/env.cgi
HTTP_CONNECTION=keep-alive
REMOTE_PORT=35287
PWD=/home/www/silo.lan/html/cgi
REDIRECT_STATUS=200
HTTP_ACCEPT_LANGUAGE=de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
REMOTE_ADDR=192.168.123.50
SHLVL=1
SERVER_NAME=silo.lan
CONTENT_LENGTH=0
SERVER_SOFTWARE=lighttpd/1.4.19
SERVER_ADDR=0.0.0.0
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.1
HTTP_ACCEPT_ENCODING=gzip,deflate
REQUEST_METHOD=GET
_=/usr/bin/env
Wenn du ein Formular mit Post zurückgeschickt hast, sollte da dann auch irgendwas mit ..POST auftauchen. Bei PHP heisst das ja nur $_POST, aber die dazugehörigen Environmentvariablen habe ich mir noch nie direkt angesehen. Jedenfalls ist es wichtig erstmal ein Gefühl für diese Variablen zu entwickeln, wenn du mit eigenen Scripten mit dem Sever kommunizieren willst.
|
Mixer
(Themenstarter)
Anmeldungsdatum: 2. Februar 2008
Beiträge: 153
Wohnort: Bayern
|
Hallo, das Skript für die Umgebungsvariablen gibt folgendes aus: GATEWAY_INTERFACE=CGI/1.1
HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
REMOTE_ADDR=169.254.7.1
HTTP_USER_AGENT=Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.04 (lucid) Firefox/3.6.17
DOCUMENT_ROOT=/var/www
REMOTE_PORT=38872
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
CONTENT_LENGTH=0
SCRIPT_FILENAME=/var/www/cgi-bin/myenv.sh
HTTP_HOST=169.254.7.7
REQUEST_URI=/cgi-bin/myenv.sh
SERVER_SOFTWARE=lighttpd/1.4.28
HTTP_CONNECTION=keep-alive
HTTP_ACCEPT_LANGUAGE=en-us,en;q=0.5
HTTP_REFERER=http://169.254.7.7/cgi-bin/
HTTP_KEEP_ALIVE=115
SERVER_PROTOCOL=HTTP/1.1
HTTP_ACCEPT_ENCODING=gzip,deflate
REDIRECT_STATUS=200
REQUEST_METHOD=GET
SERVER_ADDR=0.0.0.0
PWD=/var/www/cgi-bin
SERVER_PORT=80
SCRIPT_NAME=/cgi-bin/myenv.sh
SERVER_NAME=169.254.7.7 Ich möchte aus der html-Seite heraus auf dem Server ein Shell-Skript aufrufen. Dabei möchte ich auch noch einen Parameter übergeben. Das Shell-Skript führt dann ein paar Befehle aus und beendet sich dann wieder selbst. Die html-Seite sollte sich dabei aber am besten nicht ändern. Hoffe das war verständlicher Gruss
|
adun
Anmeldungsdatum: 29. März 2005
Beiträge: 8606
|
Das wird aufwendiger als du vielleicht denkst, wenn jemand außer dir Zugriff auf die Seite hat. Parameter wie ";eval evil" willst du bestimmt nicht ausführen.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6488
Wohnort: Hamburg
|
Wie Adun schon sagte ist das nicht ganz trivial und auch nicht ungefährlich (je nach Umgebung).
Die html-Seite sollte sich dabei aber am besten nicht ändern.
Wie gesagt, das ist ein Fall für Javascript und dafür bin ich kein Experte. Und soll der Anwender wirklich kein Feedback bekommen? Wenn er keine Reaktion erkennt wiederholt er das ganze vielleicht 20 Mal.
Das Shell-Skript führt dann ein paar Befehle aus und beendet sich dann wieder selbst.
"Ein paar Befehle" ist etwas unpräzise ausgedrückt und ich erlaube mir deshalb mal darauf hinzuweisen, dass der Server und damit auch die CGI Scripte mit den Rechten des Benutzers www-data laufen und der darf längst nicht alles was du darfst. Aber ich gebe dir mal etwas zum spielen, damit du mal ein Gefühl dafür bekommst was da ggf. auf dich zukommen könnte. Das folgende Script heisst bei mir test3.cgi. Du solltest deine Scripte übrigens auch mit der Endung CGI versehen, da die Endung bei der Methode "get" in der Adresszeile des Browsers zu sehen ist und ausserdem auch noch im Quelltext des Formulars. Man muss ja nicht gleich sehen, dass du Bash statt Perl verwendest. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 | #!/bin/bash
IP=$REMOTE_ADDR
echo Content-type: text/html
echo ""
/bin/cat << EOM
<html>
<head>
<title>Testscript</title>
</head>
<h1>Testscript CGI / Bash</h1>
EOM
MAC=$(sudo arping -c 1 $IP | grep -o '\[..:..:..:..:..:..\]' )
echo "<p>Deine IP ist: <b>$IP</b>"
if [ -n "MAC" ]; then
echo "und deine MAC Adresse ist: <b>$MAC</b>"
fi
echo "</p>"
echo "<form action=\"$SCRIPT_NAME\" method=\"get\">"
echo "<p>Eine IP Adresse eingeben: <input name=\"WUNSCHIP\"></p>"
#echo "<input type=\"submit\" name=\"send\" value=\"absenden\">"
echo "</form>"
if [ -n $QUERY_STRING ]; then
WIP=$(echo "$QUERY_STRING" | grep WUNSCHIP= | grep -Eo '[[:digit:]]{1,3}(\.[[:digit:]]{1,3}){3}')
if [ -n "$WIP" ]; then
echo "Ergebnis von <i>arping</i> für $WIP<pre>"
sudo arping -c 1 $WIP
echo "</pre>"
fi
fi
echo "<h2>Umgebungsvariablen des Servers:</h2>"
echo "<p><pre>"
env
echo "</pre></p>"
/bin/cat << EOM
<p> </p>
</body>
</html>
|
Mir ist klar, das mein Script keinen Schönheitspreis gewinnt und bei den Textmanipulationen habe ich auch etwas geschludert, aber ich hoffe das die Idee dahinter trotzdem erkennbar ist.
Mein Beispiel benutzt übrigens einen Befehl (arping), den ein normaler Benutzer nicht ausführen darf.
Damit das ganze funktioniert muss also noch der Benutzer www-data in die Datei /etc/sudoers eingetragen werden und zwar mit folgenden Angaben (unter der root-Zeile):
...
root ALL=(ALL) ALL
www-data ALL=NOPASSWD: /usr/bin/arping
...
Der Benutzer www-data darf damit nur dieses eine previligierte Kommando ausführen und dass ohne Passwort! Ach ja, ganz wichtig: Änderungen in /etc/sudoers dürfen nur mit visudo durchgeführt werden! Viel Spass beim testen.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Dakuan schrieb: Ja, Du verwendest Bash und CGI 😛
Was ist daran so lustig? Ich mache das auch manchmal, mit Lighttpd allerdings nur zum testen. Auf meinem Fileserver benutze ich allerdings ein Notfallsystem auf einem 4GB Flashmodul mit bozohttpd als Server und der kann nunmal nur CGI und Perl ist für einfache Aufgaben schon fast ein Overkill...
Das könnte schnell zu einer endlosen Diskussion ausarten. Daher beschränke ich mich mal auf die wichtigsten Dinge:
|
adun
Anmeldungsdatum: 29. März 2005
Beiträge: 8606
|
Laut manpage kann man schon allein mit i2cset -f ordentlich trouble machen, bevor man dir also weiterhelfen kann, wäre wichtig welches Publikum Zugriff auf die Seite hat.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6488
Wohnort: Hamburg
|
Eigentlich wollte ich hierzu ja nichts mehr sagen, aber jetzt muss ich doch nochmal einiges loswerden, nachdem ich alles nochmal gelesen habe. Ich denke wir sind uns einig, das Bash Scripte eher eine Notlösung für minimale Systeme sind so z.B. als Webinterface für Minimalsysteme/Embedded-Systeme. Ich mache sowas nur aus Spass am Experimentieren.
komme leider nicht drum herum - perl läuft irgendwie gar nicht...
Wenn Perl auch über CGI (und nicht FastCGI) läuft, gibt es da eigentlich keinen Unterschied. Aber möglicherweise gibt es da einige Probleme mit neueren Lighttpd Versionen. So hatte ich gerade einige Probleme meine Scripte, die unter Ubuntu 8.04 problemlos laufen auf ein aktuelles Debian System zu transferieren. Aber Perl und PHP Scripte habe ich schneller zum laufen bekommen als einface Bash Scripte!
<form action="/cgi-bin/driver_led_off.sh" method="post">
Ups, das hatte ich anfangs übersehen. Die Methode "GET" ist einfacher, da dort die Parameter in der URL übergeben werden, und wie in meinem Beispiel gezeigt, in der Variablen $QUERY_STRING enthalten sind. Bei der Methode POST ist es etwas komplizierter. Man muss $CONTENT_LENGTH Bytes über stdin einlesen. Etwa so:
if [ "$REQUEST_METHOD" == "POST" ]; then
read -n $CONTENT_LENGTH EDATEN
echo -e "POST Daten:\n<pre>$EDATEN</pre>\n"
fi
Ach ja, die Anfrage ist dann natürlich URL-codiert, aus "Dies ist ein böser Test" wird dann Dies+ist+ein+b%F6ser+Test
Ich sehe Sowas als sportliche Übung, nicht aber als gute Lösung für öffentliche Auftritte. Und so habe ich auch die ursprüngliche Frage verstanden. @Lysander URL-Dispatching ist Script intern kaum möglich bzw. aufwendig;
Ist jetzt vielleicht OT aber kannst du URL-Dispatching etwas genauer definieren? Gilt das auch für PHP? Ich bastel da nämlich an einem primitiven PHP System, wo ich den zentralen Teil auch Dispatcher genannt habe, und der ist, allerdings ohne Vorlauf (Parameter Erkennung/Validierung), gerade mal 10 bis 15 Zeilen lang.
|