Eu escrevi um script de shell para testar uma API que copia arquivos e ecoa seu progresso após cada um.
Há um intervalo de dois segundos entre cada cópia, então eu gostaria de adicionar a capacidade de pressionar qualquer tecla para pausar o script para permitir testes mais aprofundados. Em seguida, pressione qualquer tecla para continuar.
Como posso adicionar isso no menor número de linhas possível?
shell-script
blarg
fonte
fonte
sleep 10; notify-send hello
e pressionar CTRL + Z para parar,notify-send hello
seja executado. se o segundo comando está sendo executado, como é que o primeiro processo é interrompido? depois disso, se o tipofg
eu não posso ver acontecendo nada, o que é óbvio, já que segundo comando já é executadocmd; cmd; cmd;
é como escrevercmd <newline> cmd <newline> ...
. Como alternativa a um script que você pode escrever( cmd; cmd; cmd; )
, ele se comportaria como o script, por causa do subshell gerado por(
sleep 10
. quando pressiono CTRL + Z após 3 segundos e retomou após alguns segundos e percebi que o comando de suspensão morreu em menos de 7 segundos. o que é oposto ao que você disse, uma vez que os nevos de comando são interrompidos, ele é executado em segundo plano.strace
osleep
comando e descobri que é a chamada do sistemananosleep()
. Parece ser umnanosleep
comportamento definido da chamada do sistema.restart_syscall()
reinicia a chamada interrompida do sistema com um argumento de tempo que é ajustado adequadamente para contabilizar o tempo que já decorreu (incluindo o tempo em que o processo foi interrompido por um sinal). Leia essa página de manual: man7.org/linux/man-pages/man2/restart_syscall.2.htmlfg %1
ou em segundo plano (ex:)bg %1
. (se os trabalhos fornecerem apenas 1 número, ou seja, apenas 1 processo suspenso, como no exemplo ilustrado do caos: apenas[1]+ stopped sleep 10
, você poderá omitir a%n
parte. se houver vários processos em segundo plano (em execução ou interrompidos), será necessário designar o que você deseja com:%n
(ex:fg %2
ter% 2 retomado em primeiro plano))Se você quiser apenas pausar o script enquanto permanecer dentro do script, poderá usar a leitura em vez de dormir.
Você pode usar
read -t
para definir um tempo limite para a leituraread -n
ler um caractere (basta pressionar qualquer tecla) para continuar o scriptComo você não forneceu nenhum código, abaixo está um exemplo de como ele pode ser usado.
Se q for pressionado,
read -n1
impede que o script continue até que uma tecla seja pressionada.Quando uma tecla é pressionada, a verificação é redefinida e o script continua no loop normalmente.
Você também pode adicionar
stty -echo
ao início da seção estty echo
ao final para evitar que a digitação atrapalhe a saída da telafonte
Com
dd
você, você pode ler com segurança um único byte de um arquivo. Comstty
você pode definir ummin
número de bytes para qualificar uma leitura de terminal e umatime
saída em décimos de segundo. Combine esses dois e você pode ficar semsleep
totalmente, eu acho, e deixe o tempo limite de leitura do terminal fazer o trabalho para você:Esse é um pequeno exemplo de
while
loop que eu criei para você experimentar. A cada dois segundos, odd
tempo limite é excedido na tentativa de leiturastdin
- redirecionada de/dev/tty
- e owhile
loop é repetido. O tempo limite é excedido oudd
não porque você pressiona uma tecla - nesse caso, um shell interativo é chamado.Aqui está uma execução de teste - os números impressos no início de cada linha são o valor da variável shell
$SECONDS
:fonte
stty sane
depois de alterar a configuração stty, posso estar errado, mas não parece que você as redefiniu em qualquer lugar?s=$(stty -g </dev/tty)
. Imediatamente após ligardd
, restauro-o comstty "$s"
. O estado do terminal não se importa com subshells e, portanto, essas configurações permanecem independentemente do shell pai.stty sane
não é necessariamente o que você quer fazer - é melhor restaurar o estado da maneira que você o encontrou do que assumir que o estado estavasane
naquele ponto. Se eu não estivesse restaurando, essesecho
itens estariam por toda parte. Descobrir isso é em parte o motivo de eu ter chegado tão tarde - sua resposta não estava aqui quando comecei a testar.