Shell: é possível atrasar um comando sem usar `sleep '?


21

Existem substitutos, alternativas ou truques do bash para atrasar comandos sem usar sleep? Por exemplo, executando o comando abaixo sem realmente usar o modo de suspensão:

$ sleep 10 && echo "This is a test"

42
O que há de errado sleep?
Muru

5
Não há outro motivo real além da curiosidade. Eu pensei que seria interessante aprender algumas soluções alternativas. Eu acho que atpode ser um, mas não consegui encontrar nenhum exemplo de uso.
user321697

1
@ user321697 “at” é agendar trabalhos únicos. eles são executados pelo serviço atd, para não pausar seu script de shell. um caso de uso para at seria fazê-lo em um horário especificado (assíncrono) e criar um arquivo de marcador quando terminar, enquanto o script aguarda que esse arquivo apareça em um loop while. você pode obter um efeito semelhante agendando um trabalho para enviar seu script a um SIGCONT e congelando-o, enviando a si mesmo um SIGSTOP.
Grega Bremec

1
Eu vim aqui esperando que todos sugerissem um spinlock. Estou agradavelmente surpreendido com todas as respostas.
Daan van Hoek #

3
Re: "Curiosity" - em unix.stackexchange.com/help/dont-ask , observe a exigência de que "Você só deve pedir práticos, perguntas respondíveis baseado em problemas reais que você enfrenta. " - que este tem sido bem recebido apesar de ter aprovado essa diretriz, é uma exceção bastante rara.
Charles Duffy

Respostas:


17

Você tem alternativas para sleep: Eles são ate cron. Ao contrário sleepdisso, é necessário que você forneça o tempo em que precisa que eles sejam executados.

  • Verifique se o atdserviço está sendo executado executando service atd status.
    Agora, digamos que a data seja 11:17 UTC; se você precisa executar um comando às 11:25 UTC, a sintaxe é: echo "This is a test" | at 11:25.
    Agora, lembre-se de que, atdpor padrão, não estará registrando a conclusão dos trabalhos. Para mais, consulte este link . É melhor que seu aplicativo tenha seu próprio log.

  • Você pode agendar trabalhos em cron, para mais informações, consulte: man cronpara ver suas opções ou crontab -eadicionar novos trabalhos. /var/log/cronpode ser verificado para obter informações sobre a execução nos trabalhos.

A FYI sleep system call suspende a execução atual e agenda o argumento passado a ela.

EDITAR:

Como o @Gaius mencionou, você também pode adicionar minutos para o atcomando. Mas vamos dizer que o tempo é 12:30:30e agora você executou o agendador com now +1 minutes. Mesmo que 1 minuto, que se traduz em 60 segundos, tenha sido especificado, atele não espera realmente 12:31:30para executar o trabalho, mas executa o trabalho em 12:31:00. As unidades de tempo podem ser minutes, hours, days, or weeks. Para mais informações, consulteman at

por exemplo: echo "ls" | at now +1 minutes


7
Isso não é verdade, você pode agendar uma no trabalho para dizer agora um minuto, para ser executado em um minutos de tempo
Gaius

29

Com bash builtins, você pode fazer:

coproc read -t 10 && wait "$!" || true

Dormir por 10 segundos sem usar sleep. O coprocé fazer para que reado stdin seja um cano de onde nada saia.|| trueé porque waito status de saída refletirá uma entrega do SIGALRM, o que causaria a saída do shell se a errexitopção estiver configurada.

Em outras conchas:

mkshe ksh93tersleep embutido, não faz sentido usar qualquer outra coisa lá (embora ambos também suportem read -t).

zshtambém suporta read -t, mas também possui um wrapper interno select(), portanto você também pode usar:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

Se o que você quer é que as coisas cronograma a ser executado a partir de uma sessão de shell interativo, ver também o zsh/schedmódulozsh .


Você consideraria read -t 10 < /dev/zero || true?
Jeff Schaller

5
@JeffSchaller Gostaria de evitá-lo, pois é um loop ocupado.
Stéphane Chazelas

@ StéphaneChazelas Eu não esperaria que isso fosse um loop ocupado - eu esperaria que qualquer shell readfosse implementado usando select (2) ou algo semelhante (o que implica que a leitura com tempo limite seria uma boa resposta para esta pergunta). Estou expressando surpresa ao invés de contradizê-lo, mas você pode apontar para uma discussão mais aprofundada sobre isso?
Norman Gray

5
@NormanGray, /dev/zeroé um arquivo que contém uma quantidade infinita de dados (NUL bytes). Então read, lerá o máximo possível durante esses 10 segundos. Felizmente, no caso de bashnão suportar armazenamento de NUL bytes em suas variáveis, isso não consumirá nenhuma memória, mas ainda consumirá os recursos da CPU.
Stéphane Chazelas

1
O @NormanGray, se executado a partir de um terminal, /dev/stdoutseria o dispositivo tty, portanto teria efeitos colaterais (como interromper o script se executado em segundo plano) e retornaria se o usuário pressionar Enter, por exemplo. read -t 10 /dev/stdout | :funcionaria no Linux, mas apenas no Linux, enquanto coprocdeveria funcionar independentemente do sistema operacional.
Stéphane Chazelas

7

Algumas outras idéias.

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null

1
Você "roubou" minha ideia de limite de tempo / tempo limite .... +1
Rui F Ribeiro

1
Ohhhh meu, obrigado, eu estava em uma situação sem dormir, top é incrível!
Fire-Dragon-DoL

6

Como existem respostas sugerindo o uso da -t delayopção não padrão read, aqui está uma maneira de fazer uma leitura de tempo limite em um shell padrão:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

O argumento para stty timeé em décimos de segundo.


5

Usando a variável interna bash $SECONDSe um loop ocupado:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done

2
Isso faria em pausa efeito por um período que varia em algum lugar entre 9 e 10 segundos embora (devido a um bug nobash ; zshe mkshteve problemas semelhantes, mas foram corrigidos desde então)
Stéphane Chazelas

7
Uma boa maneira de fazer calor.
ctrl-alt-Delor

6
não será a primeira vez que sou acusado de estar cheio de ar quente! :)
Jeff Schaller

4

o truque mais antigo do livro:

read && echo "This is a test"

Apenas aperte Entere continuará!


Isso não acontecerá se o processo precisar ser executado sem interação ou em segundo plano, certo?
ss_iwe

Correto: Mas isso não era um dos requisitos do OP como pela pergunta original, por isso ainda uma resposta válida ... ;-)> :-)
Fabby

1
O OP especificamente fornece um exemplo (com sleep) e solicita uma alternativa equivalente sem. Então readnão analisa, desculpe. ;)
AnoE

A resposta de @AnoE Stéphane é, naturalmente, o melhor, o meu é apenas o mais antigo --- press «enter» to continue --- ;-)
Fabby

4

Nos dias de microcomputadores executando o BASIC, os atrasos eram geralmente realizados com um loop vazio:

FOR I = 1 TO 10000:NEXT

O mesmo princípio pode ser usado para inserir um atraso em um script de shell:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

Obviamente, o problema com essa abordagem é que a duração do atraso varia de máquina para máquina de acordo com a velocidade do processador (ou mesmo na mesma máquina sob cargas diferentes). Ao contrário sleep, provavelmente também maximizará sua CPU (ou um de seus núcleos).


2
Uma boa maneira de fazer calor.
ctrl-alt-Delor

2
Loops de atraso são uma péssima idéia para qualquer coisa, exceto o mais curto sono (alguns nanossegundos ou ciclos de clock em um driver de dispositivo) em qualquer CPU moderna que possa executar um sistema operacional semelhante ao Unix. ou seja, um sono tão curto que você não pode ter utilidade para que a CPU faça outra coisa enquanto aguarda, como agendar outro processo ou entrar em um estado de sono de baixa energia antes de acordar com uma interrupção do timer. A freqüência dinâmica da CPU torna impossível calibrar um loop de atraso para contagens por segundo, exceto como um atraso mínimo, potencialmente dormindo muito mais em baixas velocidades de clock antes de aumentar.
Peter Cordes

Os computadores antigos tinham um consumo de energia muito menos dependente da carga de trabalho. As CPUs modernas precisam desligar dinamicamente partes diferentes do chip o máximo possível para não derreter (por exemplo, desligar partes das unidades de execução FPU ou SIMD enquanto apenas o código inteiro estiver em execução ou, pelo menos, bloquear o sinal do relógio nas partes do chip que não precisa ser alternado). E entrar em um estado de suspensão de baixa energia quando ocioso (em vez de girar em um loop infinito aguardando interrupções no cronômetro) também é mais recente do que os computadores antigos mencionados.
Peter Cordes

Para saber mais sobre o histórico da CPU, consulte Microprocessadores modernos Um guia de 90 minutos! - lighterra.com/papers/modernmicroprocessors .
Peter Cordes

3

Não existe um built-in que faça o mesmo que sleep(a menos quesleep esteja embutido). No entanto, existem outros comandos que aguardam.

Alguns incluem.

  • ate cron: usado para agendar tarefas em um horário específico.

  • inotifywait: usado para aguardar um arquivo ou arquivos serem modificados / removidos / adicionados / etc


Obrigado por isso. Você poderia fornecer um exemplo para executar uma tarefa agendada (daqui a 10 segundos) at?
user321697

1
uma edição e um voto positivo! ;-)
Fabby

cronarmazenar tarefas crontab, certo? Onde atarmazena os dados agendados?
user321697

@ user321697 Já respondeu aqui
Fabby

Sorry for voltando sua edição da Q: você mudou principal objetivo do PO da questão que invalidaria a resposta mais simples de todos ... ¯ \ _ (ツ) _ / ¯
Fabby

3

Um clássico da Terra do Windows e dos lotes:

ping -c 11 localhost >/dev/null && echo "This is a test"

A configuração incorreta do firewall ou do sistema de nomes pode causar um atraso adicional significativo.
espectros

1
127.0.0.1 ... @spectras
AnoE

1
Felizmente, não é mais necessário, pois o Windows agora suporta o sono nativamente.
precisa

1
@AnoE> resolve a parte do sistema de nomes, não a parte do firewall. Embora não seja comum, ele pode ser configurado para eliminar silenciosamente pings na interface local. Isso fará com que o ping aguarde muito mais tempo.
espectros

+1 para as memórias "afeiçoadas"
AC

0

Se você quiser esperar interativamente por uma nova linha em um arquivo,

tail -f
.

Esperando uma alteração em um sistema de arquivos? Então use por exemplo

inotify / inoticoming
.

E há outras opções, dependendo do que você quer dizer com "espera".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.