Ho uno script di shell che legge da input standard . In rare circostanze, non ci sarà nessuno pronto a fornire input e lo script deve scadere . In caso di timeout, lo script deve eseguire un codice di pulizia. Qual è il modo migliore per farlo?
Questo script deve essere molto portatile , compresi i sistemi unix del 20 ° secolo senza un compilatore C e i dispositivi integrati che eseguono busybox, quindi Perl, bash, qualsiasi linguaggio compilato e persino l'intero POSIX.2 non possono essere invocati. In particolare, $PPID
, read -t
trappole e perfettamente conforme a POSIX non sono disponibili. È anche esclusa la scrittura su un file temporaneo; lo script potrebbe essere eseguito anche se tutti i filesystem sono montati in sola lettura.
Solo per rendere le cose più difficili, voglio anche che la sceneggiatura sia ragionevolmente veloce quando non scade. In particolare, utilizzo anche lo script in Windows (principalmente in Cygwin), dove fork ed exec sono particolarmente bassi, quindi voglio ridurre al minimo il loro utilizzo.
In poche parole, ho
trap cleanup 1 2 3 15
foo=`cat`
e voglio aggiungere un timeout. Non posso sostituirlo cat
con quello read
integrato. In caso di timeout, voglio eseguire la cleanup
funzione.
Sfondo: questo script indovina la codifica del terminale stampando alcuni caratteri a 8 bit e confrontando la posizione del cursore prima e dopo. L'inizio dello script verifica che stdout sia collegato a un terminale supportato, ma a volte l'ambiente si trova (ad esempio plink
imposta TERM=xterm
anche se viene chiamato conTERM=dumb
). La parte rilevante dello script è simile alla seguente:
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
Come posso modificare lo script in modo tale che se tr
non ha letto alcun input dopo 2 secondi, viene ucciso e lo script esegue la cleanup
funzione?