Mam skrypt powłoki, który odczytuje ze standardowego wejścia . W rzadkich przypadkach nikt nie będzie gotowy do wprowadzenia danych, a skrypt musi upłynąć limit czasu . W przypadku przekroczenia limitu czasu skrypt musi wykonać kod czyszczenia. Jak najlepiej to zrobić?
Skrypt ten musi być bardzo przenośny , w tym do systemów unixowych XX wieku bez kompilatora C oraz do urządzeń wbudowanych z uruchomionym busyboxem, więc nie można polegać na Perlu, bash, dowolnym języku kompilowanym, a nawet pełnym POSIX.2. W szczególności $PPID
, read -t
i pułapki idealnie POSIX nie są dostępne. Zapisywanie do pliku tymczasowego jest również wykluczone; skrypt może działać, nawet jeśli wszystkie systemy plików są zamontowane tylko do odczytu.
Żeby było trudniej, chcę, aby skrypt był dość szybki, gdy nie upłynie limit czasu. W szczególności używam również skryptu w systemie Windows (głównie w Cygwin), gdzie rozwidlenie i exec są szczególnie niskie, więc chcę ograniczyć ich użycie do minimum.
W skrócie, mam
trap cleanup 1 2 3 15
foo=`cat`
i chcę dodać limit czasu. Nie mogę wymienić cat
z read
zabudowy. W przypadku przekroczenia limitu czasu chcę wykonać tę cleanup
funkcję.
Tło: ten skrypt zgaduje kodowanie terminala, drukując jakieś 8-bitowe znaki i porównując pozycję kursora przed i po. Początek skryptu testuje, że stdout jest podłączony do obsługiwanego terminala, ale czasami środowisko leży (np. plink
Ustawia, TERM=xterm
nawet jeśli jest wywoływaneTERM=dumb
). Odpowiednia część skryptu wygląda następująco:
text='Éé' # UTF-8; shows up as Ãé on a latin1 terminal
csi='␛['; dsr_cpr="${csi}6n"; dsr_ok="${csi}5n" # ␛ is an escape character
stty_save=`stty -g`
cleanup () { stty "$stty_save"; }
trap 'cleanup; exit 120' 0 1 2 3 15 # cleanup code
stty eol 0 eof n -echo # Input will end with `0n`
# echo-n is a function that outputs its argument without a newline
echo-n "$dsr_cpr$dsr_ok" # Ask the terminal to report the cursor position
initial_report=`tr -dc \;0123456789` # Expect ␛[42;10R␛[0n for y=42,x=10
echo-n "$text$dsr_cpr$dsr_ok"
final_report=`tr -dc \;0123456789`
cleanup
# Compute and return initial_x - final_x
Jak mogę zmodyfikować skrypt, aby jeśli tr
nie odczytał żadnych danych wejściowych po 2 sekundach, został zabity, a skrypt wykonuje cleanup
funkcję?