AKTUALISIEREN- sieht so aus, als wäre das etwas Eigenartiges bei Bash 4.3.42, da es mit 4.3.46 einwandfrei funktioniert. Ich hinterlasse diesen Beitrag für diejenigen, die in Zukunft auf dasselbe Problem stoßen.
Wenn ich diesen Befehl in der Bash-Befehlszeile ausführe, funktioniert er ordnungsgemäß:
% (TMOUT=3; s="no selection"; select s in a b c ; do break ; done; echo $s)
1) a
2) b
3) c
#?
no selection
% _
Ergebnis: zeigtkeine Auswahlund kehrt zur Befehlszeile zurück.
Wenn ich jedoch ein Skript platziere und es ausführe, werde ich wiederholt zur Auswahl aufgefordert.
% cat a.sh
#!/bin/bash
(TMOUT=3; s="no selection"; select s in a b c ; do break ; done; echo $s)
% ./a.sh
Ergebnis:
1) a
2) b
3) c
#? 1) a
2) b
3) c
#? 1) a
2) b
3) c
#? ^C
% _
Warum ist das so? Meine Hauptfrage ist -wie lässt sich das in einem Skript zum Laufen bringen?!
AKTUALISIERT
% bash --version
GNU bash, version 4.3.42(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
% uname
Linux lx1 2.6.32-642.6.2.el6.x86_64 #1 SMP Mon Oct 24 10:22:33 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
Antwort1
Aus dem Handbuch:
TMOUT Wenn TMOUT auf einen Wert größer als Null gesetzt ist, wird es als Standard-Timeout für das integrierte Lese-Befehlselement behandelt. Der Select-Befehl wird beendet, wenn die Eingabe nach TMOUT Sekunden nicht eintrifft, wenn die Eingabe von einem Terminal kommt. In einer interaktiven Shell wird der Wert als Anzahl der Sekunden interpretiert, die nach der Ausgabe der primären Eingabeaufforderung auf eine Eingabe gewartet werden soll. Bash wird beendet, wenn diese Anzahl von Sekunden gewartet wird und keine Eingabe eintrifft.
Der erste Fall ist also auf die interaktive Shell zurückzuführen.
$ ps -aef|grep bash; echo "before"; (TMOUT=3; s="no selection"; ps -aef|grep bash; select s in a b c ; do break ; done; echo $s;ps -aef|grep bash);echo "after";ps -aef|grep bash
asktyagi 4926 23767 0 09:40 pts/0 00:00:00 grep --color=auto bash
asktyagi 23767 23741 0 09:03 pts/0 00:00:00 -bash
**before**
asktyagi 4927 23767 0 09:40 pts/0 00:00:00 -bash
asktyagi 4929 4927 0 09:40 pts/0 00:00:00 grep --color=auto bash
asktyagi 23767 23741 0 09:03 pts/0 00:00:00 -bash
1) a
2) b
3) c
#?
no selection
asktyagi 4927 23767 0 09:40 pts/0 00:00:00 -bash
asktyagi 4931 4927 0 09:40 pts/0 00:00:00 grep --color=auto bash
asktyagi 23767 23741 0 09:03 pts/0 00:00:00 -bash
**after**
asktyagi 4933 23767 0 09:40 pts/0 00:00:00 grep --color=auto bash
asktyagi 23767 23741 0 09:03 pts/0 00:00:00 -bash
Jetzt mit Skript
$ cat a.sh
#!/bin/bash
(TMOUT=3; s="no selection"; select s in a b c ; do break ; done; echo $s)
ps -aef|grep bash
$ sh a.sh
1) a
2) b
3) c
#?
no selection
asktyagi 5201 5188 0 09:41 pts/0 00:00:00 grep bash
asktyagi 23767 23741 0 09:03 pts/0 00:00:00 -bash
Antwort2
Verwenden Sie den timeout
Befehl. Dieses Beispiel könnte verbessert werden, aber es macht den Punkt deutlich. Verwenden Sie zuerst den in bash integrierten trap
Befehl, um beim Beenden etwas auszuführen, und führen Sie dann Ihre Schleife aus. Sie läuft wie folgt ab:
#] timeout 3s sh -c 'trap "echo no selection" EXIT; select s in a b c ; do break ; done; '
1) a
2) b
3) c
#? <waits 3 seconds>no selection
Antwort3
Letztendlich habe ich also meine eigene Auswahl geschrieben, die in einem Skript verwendet werden kann.
# $1 timeout
# rest - selection
function select_ {
t=$1
shift
arr=($*)
i=1
for a in $*; do
echo "$i) $a" >$(tty)
((i++))
done
echo "TIMEOUT: In ${t} seconds ${arr[0]} will be automatically selected." >$(tty)
printf "#? " >$(tty)
read -t $t x
[ "$x" == "" ] && {
x=1
echo "$x" >$(tty)
}
((x=x+0))
[ "$x" -ge 1 -a "$x" -le ${#arr[@]} ] && {
((x--))
echo ${arr[$x]}
}
}
So verwenden Sie es:
select_ 10 a b c
Beispiel:
$ ./x.sh
1) a
2) b
3) c
TIMEOUT: In 10 seconds a will be automatically selected.
#? 2
b
$ ./x.sh
1) a
2) b
3) c
TIMEOUT: In 10 seconds a will be automatically selected.
#? 1
a