Eu tenho um script de shell que está lendo da entrada padrão . Em raras circunstâncias, não haverá ninguém pronto para fornecer informações, e o script deve expirar . Em caso de tempo limite, o script deve executar algum código de limpeza. Qual é a melhor maneira de fazer isso?
Esse script deve ser muito portátil , incluindo sistemas unix do século XX sem um compilador C e dispositivos incorporados executando o busybox, para que Perl, bash, qualquer linguagem compilada e até mesmo o POSIX.2 completo não sejam confiáveis. Em particular, $PPID
, read -t
armadilhas e perfeitamente compatíveis com POSIX não estão disponíveis. A gravação em um arquivo temporário também é excluída; o script pode ser executado mesmo que todos os sistemas de arquivos sejam montados somente leitura.
Apenas para tornar as coisas mais difíceis, também quero que o script seja razoavelmente rápido quando não tiver tempo limite. Em particular, eu também uso o script no Windows (principalmente no Cygwin), onde fork e exec são particularmente baixos, por isso quero manter seu uso no mínimo.
Em poucas palavras, eu tenho
trap cleanup 1 2 3 15
foo=`cat`
e quero adicionar um tempo limite. Não posso substituir cat
pelo read
incorporado. Em caso de tempo limite, desejo executar a cleanup
função.
Antecedentes: esse script está adivinhando a codificação do terminal, imprimindo alguns caracteres de 8 bits e comparando a posição do cursor antes e depois. O início do script testa que stdout está conectado a um terminal suportado, mas às vezes o ambiente está mentindo (por exemplo, plink
define TERM=xterm
mesmo que seja chamado comTERM=dumb
). A parte relevante do script fica assim:
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
Como posso modificar o script para que, se tr
não tiver lido nenhuma entrada após 2 segundos, ele seja morto e o script execute a cleanup
função?