Maybe OT: Problem mit Shell-Programmierung auf einem embedded Linux
Hallo Liste, es steht schon im subject: mein Problem ist kein SuSE-spezifisches. Hoffentlich kriege ich trotzdem viele Antworten. Das Ganze spielt sich auf einem kleinen SBC ab, der mit einem Kernel 2.4.18 und einer busybox 0.60-irgendwas läuft. Ich habe aber inzwischen auch eine echte bash da drauf, das Ergebnis ist aber gleich. Folgendes: Ich möchte in einem Shellscript eine Abfrage starten, bei der ein User entwerder per Tastendruck eine Aktion auslöst oder eben nicht, und falls da niemand drückt, soll nach ein paar Sekunden das Skript einfach weiterlaufen. Zuerst habe ich es mit "select" versucht, macht ja schön schnell und einfach ein kleines Menü, allerdings habe ich da keine Timeout-Funktion gefunden. Dann lese ich eben mit "read" und der Option -t von stdin und werte daß dann aus. Funktioniert alles wunderbar, wenn ich das Skript von Hand starte. Aber nicht, wenn das Script automatisch von einem init-Script beim Booten gestartet wird. Dann bekomme ich immer nur mit, daß die Timeout-Zeit schon erreicht ist, auch wenn da z.B. "read -t 2000 VARIABLE" steht. Ist das normal? Habe ich etwas übersehen? Wenn ja, was? Gibt es eine andere Möglichkeit für ein Menü mit Timeout? Ich kann das zumindest mit meinem Arbeitsrechner unter SuSE 8.2 nicht nachstellen. Vielen Dank für jede Antwort, mfG, Jens
Jens Nixdorf schrieb am Tue, 17 Feb 2004 00:00:25 +0100: Maybe OT: Problem mit Shell-Programmierung auf einem embedded Linux
Hallo Liste,
es steht schon im subject: mein Problem ist kein SuSE-spezifisches. Hoffentlich kriege ich trotzdem viele Antworten. Das Ganze spielt sich auf einem kleinen SBC ab, der mit einem Kernel 2.4.18 und einer busybox 0.60-irgendwas läuft. Ich habe aber inzwischen auch eine echte bash da drauf, das Ergebnis ist aber gleich.
Folgendes: Ich möchte in einem Shellscript eine Abfrage starten, bei der ein User entwerder per Tastendruck eine Aktion auslöst oder eben nicht, und falls da niemand drückt, soll nach ein paar Sekunden das Skript einfach weiterlaufen.
Zuerst habe ich es mit "select" versucht, macht ja schön schnell und einfach ein kleines Menü, allerdings habe ich da keine Timeout-Funktion gefunden.
Dann lese ich eben mit "read" und der Option -t von stdin und werte daß dann aus.
Funktioniert alles wunderbar, wenn ich das Skript von Hand starte. Aber nicht, wenn das Script automatisch von einem init-Script beim Booten gestartet wird. Dann bekomme ich immer nur mit, daß die Timeout-Zeit schon erreicht ist, auch wenn da z.B. "read -t 2000 VARIABLE" steht. Ist das normal? Habe ich etwas übersehen? Wenn ja, was? Gibt es eine andere Möglichkeit für ein Menü mit Timeout? Ich kann das zumindest mit meinem Arbeitsrechner unter SuSE 8.2 nicht nachstellen.
Vielen Dank für jede Antwort,
mfG, Jens
Hallo, ja wenn Du das Zeug beim booten startest, hat es kein kontrollierendes Terminal, d.h. stdin/stdout/stderr fehlen resp. werden durch /dev/null oder so geliefert. In so einem Falle mußt Du sie AFAIK umlenken: z.B. read -t 2000 VARIABLE
Joerg Thuemmler schrieb:
ja wenn Du das Zeug beim booten startest, hat es kein kontrollierendes Terminal, d.h. stdin/stdout/stderr fehlen resp. werden durch /dev/null oder so geliefert. In so einem Falle mußt Du sie AFAIK umlenken: z.B. read -t 2000 VARIABLE
Danke, das hat mich schon ein gutes Stück weitergebracht, jetzt ist der Timeout wenigstens noch nicht erreicht und das Skript wartet schön auf mich. Dafür nimmt es Script jetzt die Eingabe nicht so an wie es soll. Hmpf. Hier der Code: echo "1: Aktion 1" echo "2: Aktion 2" read -t 25 AUSWAHL < /dev/tty1 if [ "$AUSWAHL" = "1" ]; then echo "1 gedrückt" elif [ "$AUSWAHL" = "2" ]; then echo "2 gedrückt" else echo "Timeout erreicht" fi Wenn ich jetzt innerhalb der 25 s die 1 oder 2 eingebe, sagt mir das Script nur: "1 nicht gefunden" oder "2 nicht gefunden". Leider reagiert das Script auch nicht auf folgenden Eintrag in der ersten Zeile: #!/bin/bash -x womit ich ja sonst wenigstens etwas mehr sehen könnte, was das Script macht. Ich habe auch schon mit den Parametern von read rumgespielt, z.B. einen Prompt gesetzt (-p PROMPT) usw. Auch rufe ich das Script jetzt erst in .profile auf. Was kann da jetzt noch falsch sein? mfG, Jens
Jens Nixdorf schrieb:
Wenn ich jetzt innerhalb der 25 s die 1 oder 2 eingebe, sagt mir das Script nur: "1 nicht gefunden" oder "2 nicht gefunden". Leider reagiert das Script auch nicht auf folgenden Eintrag in der ersten Zeile:
Nachtrag: Ich habe soeben bemerkt, dass dieses Verhalten nur auftritt, wenn ich den Timeout bei read nutzen will. Lasse ich -t weg, funktioniert alles, aber leider _muss_ ja dann irgendwer 'ne Taste drücken, das Ganze blockiert sich. Das darf ja auch wieder nicht sein. Gibt es da Möglichkeiten in der Shell-Programmierung, die so etwas umgehen?
Hallo Joerg, probier das Script mal aus, wenn du auf der ersten Textconsole eingeloggt bist. read -t 2000 VARIABLE
Joerg Thuemmler schrieb:
ja wenn Du das Zeug beim booten startest, hat es kein kontrollierendes Terminal, d.h. stdin/stdout/stderr fehlen resp. werden durch /dev/null oder so geliefert. In so einem Falle mußt Du sie AFAIK umlenken: z.B. read -t 2000 VARIABLE
Danke, das hat mich schon ein gutes Stück weitergebracht, jetzt ist der Timeout wenigstens noch nicht erreicht und das Skript wartet schön auf mich. Dafür nimmt es Script jetzt die Eingabe nicht so an wie es soll. Hmpf.
Hier der Code:
echo "1: Aktion 1" echo "2: Aktion 2" read -t 25 AUSWAHL < /dev/tty1 if [ "$AUSWAHL" = "1" ]; then echo "1 gedrückt" elif [ "$AUSWAHL" = "2" ]; then echo "2 gedrückt" else echo "Timeout erreicht" fi
Wenn ich jetzt innerhalb der 25 s die 1 oder 2 eingebe, sagt mir das Script nur: "1 nicht gefunden" oder "2 nicht gefunden". Leider reagiert das Script auch nicht auf folgenden Eintrag in der ersten Zeile:
#!/bin/bash -x
womit ich ja sonst wenigstens etwas mehr sehen könnte, was das Script macht. Ich habe auch schon mit den Parametern von read rumgespielt, z.B. einen Prompt gesetzt (-p PROMPT) usw. Auch rufe ich das Script jetzt erst in .profile auf.
Was kann da jetzt noch falsch sein?
mfG, Jens
Alexander Balsam schrieb am 17 Feb 2004 17:37:46 +0100: Maybe OT: Problem mit Shell-Programmierung auf einem embedded Linux
Hallo Joerg,
probier das Script mal aus, wenn du auf der ersten Textconsole eingeloggt bist. read -t 2000 VARIABLE
Gruß
Alexander
ja logo. Genau so geht das. Du kannst einem script halt nur ein kontrollierendes Terminal (besteht aus stdin/stdout/stderr) zuweisen. Wenn Du es manuell startest, erledigt diese Zuweisung halt die shell. Aber auch dann kannst Du nicht die Konsole wechseln und dort was eingeben, natürlich wird die für diese Konsole zuständige Anwendung (entweder ein getty oder ne shell) das als Eingabe für sich betrachten und nicht für Dein auf tty1 gestartetes script! Und da von init (oder anderen selbst konsoleungebundenen Prozessen, wie cron) gestartete Prozesse eben kein kontrollierendes Terminal haben, kannst Du ihnen genau _1_ zuweisen via Umlenkung. Wo ist das Problem? [tofu gelöscht] cu -- Joerg Thuemmler sysadmin@vordruckleitverlag.de Vordruck Leitverlag GmbH Berlin, ZNL Freiberg Halsbruecker Str. 31b, 09599 Freiberg, Germany Tel. +49 (0)3731/303121
Jens Nixdorf schrieb am Tue, 17 Feb 2004 16:17:30 +0100: Maybe OT: Problem mit Shell-Programmierung auf einem embedded Linux
Joerg Thuemmler schrieb:
ja wenn Du das Zeug beim booten startest, hat es kein kontrollierendes Terminal, d.h. stdin/stdout/stderr fehlen resp. werden durch /dev/null oder so geliefert. In so einem Falle mußt Du sie AFAIK umlenken: z.B. read -t 2000 VARIABLE
Danke, das hat mich schon ein gutes Stück weitergebracht, jetzt ist der Timeout wenigstens noch nicht erreicht und das Skript wartet schön auf mich. Dafür nimmt es Script jetzt die Eingabe nicht so an wie es soll. Hmpf.
Hier der Code:
echo "1: Aktion 1" echo "2: Aktion 2" read -t 25 AUSWAHL < /dev/tty1 if [ "$AUSWAHL" = "1" ]; then echo "1 gedrückt" elif [ "$AUSWAHL" = "2" ]; then echo "2 gedrückt" else echo "Timeout erreicht" fi
Wenn ich jetzt innerhalb der 25 s die 1 oder 2 eingebe, sagt mir das Script nur: "1 nicht gefunden" oder "2 nicht gefunden". Leider reagiert das Script auch nicht auf folgenden Eintrag in der ersten Zeile:
#!/bin/bash -x
womit ich ja sonst wenigstens etwas mehr sehen könnte, was das Script macht. Ich habe auch schon mit den Parametern von read rumgespielt, z.B. einen Prompt gesetzt (-p PROMPT) usw. Auch rufe ich das Script jetzt erst in .profile auf.
Was kann da jetzt noch falsch sein?
mfG, Jens
Jepp, das ist klar, hab ich gerade nicht dran gedacht, da ich das bislang nur mal für stderr/stdout genutzt habe: Du mußt natürlich eine sonstige Eingabeerwartung verhindern, d.h. den Gettyprozeß für diese Konsole rausnehmen. Das geschieht AFAIK über einen entsprechenden Eintrag in der /etc/inittab. Am besten, Du testest es erstmal mit tty2 oder höher (dann hast Du die tty1 immer noch im Zugriff, wenns nicht gleich klappt). Zeile für tty2 auskommentieren, "kill -HUP 1" aufrufen (init restarten), dann wird tty2 kein Login mehr annehmen und Du kannst das script von da lesen lassen...
Joerg Thuemmler schrieb:
Jepp, das ist klar, hab ich gerade nicht dran gedacht, da ich das bislang nur mal für stderr/stdout genutzt habe: Du mußt natürlich eine sonstige Eingabeerwartung verhindern, d.h. den Gettyprozeß für diese Konsole rausnehmen. Das geschieht AFAIK über einen entsprechenden Eintrag in der /etc/inittab. Am besten, Du testest es erstmal mit tty2 oder höher (dann hast Du die tty1 immer noch im Zugriff, wenns nicht gleich klappt). Zeile für tty2 auskommentieren, "kill -HUP 1" aufrufen (init restarten), dann wird tty2 kein Login mehr annehmen und Du kannst das script von da lesen lassen...
Hallo Joerg, da hab ich wohl wichtige Info's unterschlagen (weil ich nicht dachte, dass die wichtig sind): Das Linux hat nur eine Konsole. Kein tty2 oder 3. Keine Runlevel. Es wird kein getty gestartet. Inittab besteht nur aus 3 Einträgen: ::sysinit:/etc/rc.sysinit ::respawn:/bin/login -f USER ::ctrlaltdel:/sbin/reboot Mehr passiert da nicht. Der User, der da automatisch eingeloggt wird, hat in seiner .profile-Datei das Script, um das es hier geht, drinstehen. Ausserdem: Wieso funktioniert das Ganze denn ohne Timeout? Ich kann, solange ich den Timeout-Schalter weglasse, das Script inklusive Eingabe benutzen. Nur wenn der Timeout gesetzt ist, werden meine Eingaben nicht mehr "gefunden". Bin echt ratlos. mfG, Jens
Jens Nixdorf schrieb am Wed, 18 Feb 2004 11:34:03 +0100: Maybe OT: Problem mit Shell-Programmierung auf einem embedded Linux
Joerg Thuemmler schrieb:
Jepp, das ist klar, hab ich gerade nicht dran gedacht, da ich das bislang nur mal für stderr/stdout genutzt habe: Du mußt natürlich eine sonstige Eingabeerwartung verhindern, d.h. den Gettyprozeß für diese Konsole rausnehmen. Das geschieht AFAIK über einen entsprechenden Eintrag in der /etc/inittab. Am besten, Du testest es erstmal mit tty2 oder höher (dann hast Du die tty1 immer noch im Zugriff, wenns nicht gleich klappt). Zeile für tty2 auskommentieren, "kill -HUP 1" aufrufen (init restarten), dann wird tty2 kein Login mehr annehmen und Du kannst das script von da lesen lassen...
Hallo Joerg,
da hab ich wohl wichtige Info's unterschlagen (weil ich nicht dachte, dass die wichtig sind): Das Linux hat nur eine Konsole. Kein tty2 oder 3. Keine Runlevel. Es wird kein getty gestartet. Inittab besteht nur aus 3 Einträgen:
::sysinit:/etc/rc.sysinit ::respawn:/bin/login -f USER ::ctrlaltdel:/sbin/reboot
Mehr passiert da nicht. Der User, der da automatisch eingeloggt wird, hat in seiner .profile-Datei das Script, um das es hier geht, drinstehen.
Ausserdem: Wieso funktioniert das Ganze denn ohne Timeout? Ich kann, solange ich den Timeout-Schalter weglasse, das Script inklusive Eingabe benutzen. Nur wenn der Timeout gesetzt ist, werden meine Eingaben nicht mehr "gefunden". Bin echt ratlos.
mfG, Jens
hmm, das ist natürlich was anderes. Wenn es über die .profile gestartet wird, hat es ja auch ein kontrollierendes Terminal. Ich hatte Dich so verstanden, daß es vom System (init oder so) gestartet wird. Deine shell versteht die -t -Option? Nicht alle Shells scheinen das zu kennen... Mit der bash der Suse 8.1 klappt sowas jedenfalls in der .profile anstandslos. Ich würde den Fehler so bei der Shell vermuten, entweder sie kanns nicht richtig oder Du läßt es von der .profile aus unter einer ablaufen, die es nicht kann, z.B. weil nicht "#!/bin/bash" als erste Zeile steht. hth -- Joerg Thuemmler sysadmin@vordruckleitverlag.de Vordruck Leitverlag GmbH Berlin, ZNL Freiberg Halsbruecker Str. 31b, 09599 Freiberg, Germany Tel. +49 (0)3731/303121
Joerg Thuemmler schrieb:
hmm, das ist natürlich was anderes. Wenn es über die .profile gestartet wird, hat es ja auch ein kontrollierendes Terminal. Ich hatte Dich so verstanden, daß es vom System (init oder so) gestartet wird.
War am Anfang auch so, habe ich dann geändert. Steht auch in einer der Mails.
Deine shell versteht die -t -Option? Nicht alle Shells scheinen das zu kennen... Mit der bash der Suse 8.1 klappt sowas jedenfalls in der .profile anstandslos. Ich würde den Fehler so bei der Shell vermuten, entweder sie kanns nicht richtig oder Du läßt es von der .profile aus unter einer ablaufen, die es nicht kann, z.B. weil nicht "#!/bin/bash" als erste Zeile steht.
Ich habe jetzt busybox auf Version 1.0 pre7 "upgedatet", leider wird der Schalter -t auch hier nicht verstanden. Jedenfalls nicht, wenn das Script automatisch startet. Ich habe ja auch eine bash auf dem System, aber ich weiß erstens nicht, wie ich diese Bash aus dem Startscript heraus starte und sie dann ein anderes Script (mit der eigentlichen Abfrage) starten lasse. Und zweitens, was wenn auch die Bash das -t nicht versteht, wenn sie automatisch gestartet wird? Eigentlich ist mir auch egal, wie es geht. Hauptsache es geht irgendwie ;) Es muss nicht mit 'read' sein, ich kenne nur nix anderes, was nicht blockiert. mfG, Jens
Jens Nixdorf schrieb am Wed, 18 Feb 2004 17:37:27 +0100: Maybe OT: Problem mit Shell-Programmierung auf einem embedded Linux
Joerg Thuemmler schrieb: ...
Ich habe jetzt busybox auf Version 1.0 pre7 "upgedatet", leider wird der Schalter -t auch hier nicht verstanden. Jedenfalls nicht, wenn das Script automatisch startet. Ich habe ja auch eine bash auf dem System, aber ich weiß erstens nicht, wie ich diese Bash aus dem Startscript heraus starte und sie dann ein anderes Script (mit der eigentlichen Abfrage) starten lasse. Und zweitens, was wenn auch die Bash das -t nicht versteht, wenn sie automatisch gestartet wird?
Eigentlich ist mir auch egal, wie es geht. Hauptsache es geht irgendwie ;) Es muss nicht mit 'read' sein, ich kenne nur nix anderes, was nicht blockiert.
mfG, Jens
Hmm, ehrlich gesagt, da weiß ich auch nicht weiter. Die Bash zum Abarbeiten des scripts kriegst Du aber ganz einfach: erste Zeile des scripts: #!/bin/bash wenn wir mal annehmen, daß die bash in /bin liegt. Allerdings, wenn eine bash drauf ist, wird das wohl sowieso die Standardshell sein. Blöde Sache, wahrscheinlich würde ich mir jetzt langsam ein C-Kommando read_with_timeout schreiben, was das macht. Obwohl ich nicht verstehe, _was_ da bei Dir schiefläuft. cu -- Joerg Thuemmler sysadmin@vordruckleitverlag.de Vordruck Leitverlag GmbH Berlin, ZNL Freiberg Halsbruecker Str. 31b, 09599 Freiberg, Germany Tel. +49 (0)3731/303121
Joerg Thuemmler schrieb:
Hmm, ehrlich gesagt, da weiß ich auch nicht weiter. Die Bash zum Abarbeiten des scripts kriegst Du aber ganz einfach: erste Zeile des scripts:
#!/bin/bash
Leider nicht, es startet immer busybox builtin-shell. Bash muss ich extra aufrufen. Das liegt wohl an tiny-login, welches ich nutze, was auch zu busybox gehört. Ein "richtiges" login hat Probleme auf dem System, weil zum Zeitpunkt des Einloggens noch alles schreibgeschützt ist. Login kommt dann mit Fehlern, dass es Berechtigungen nicht setzen kann. Aber das ist 'ne andere Sache. Im Moment habe ich die abenteuerlichsten Sachen gemacht, um zu einem Ergebnis zu kommen. Ich starte aus dem ersten Script ein kleines C-Programm im Hintergrund mit einer read-Abfrage (ohne Timeout). Wenn da ein User eine Taste drückt, wird eine temp. Datei angelegt und das Programm beendet. Das erste Script schaut dann nach einer Wartezeit nach ob die temp. Datei da ist, wenn ja, läuft es in die eine Richtung, wenn nicht, in die andere Richtung. Zusätzlich killt es noch das C-Programm, falls das noch läuft. Das ist so schlecht, das mir übel wird, aber es erfüllt momentan seinen Zweck. Jetzt habe ich Ruhe, um andere Vorschläge zu testen. Auf jeden Fall erst mal vielen Dank für die Tipps (auch an die anderen Antworter), haben mich schon viel weitergebracht. mfG, Jens
Jens Nixdorf schrieb:
Joerg Thuemmler schrieb:
hmm, das ist natürlich was anderes. Wenn es über die .profile gestartet wird, hat es ja auch ein kontrollierendes Terminal. Ich hatte Dich so verstanden, daß es vom System (init oder so) gestartet wird.
War am Anfang auch so, habe ich dann geändert. Steht auch in einer der Mails.
Deine shell versteht die -t -Option? Nicht alle Shells scheinen das zu kennen... Mit der bash der Suse 8.1 klappt sowas jedenfalls in der .profile anstandslos. Ich würde den Fehler so bei der Shell vermuten, entweder sie kanns nicht richtig oder Du läßt es von der .profile aus unter einer ablaufen, die es nicht kann, z.B. weil nicht "#!/bin/bash" als erste Zeile steht.
Ich habe jetzt busybox auf Version 1.0 pre7 "upgedatet", leider wird der Schalter -t auch hier nicht verstanden. Jedenfalls nicht, wenn das Script automatisch startet. Ich habe ja auch eine bash auf dem System, aber ich weiß erstens nicht, wie ich diese Bash aus dem Startscript heraus starte und sie dann ein anderes Script (mit der eigentlichen Abfrage) starten lasse. Und zweitens, was wenn auch die Bash das -t nicht versteht, wenn sie automatisch gestartet wird?
Eigentlich ist mir auch egal, wie es geht. Hauptsache es geht irgendwie ;) Es muss nicht mit 'read' sein, ich kenne nur nix anderes, was nicht blockiert.
Hi, ich hab da so ein Codeschnipsel fuer Dich... -----8<----- int=1 stty -icanon min 0 time 0 while test $int -lt 3000 do read chlog if test $chlog then clear break 1 fi int=`expr $int + 1` done stty icanon clocal echoe eof "^D" if test $int -ge 3000 then clear echo "" echo "$int Anmelde- Timeout ! Abmeldung erfolgt automatisch.. " exit fi echo "$chlog" ------8<---------
mfG, Jens
-- Gruss Bernd
participants (4)
-
Alexander Balsam
-
Illuminatus@t-online.de
-
Jens Nixdorf
-
Joerg Thuemmler