Como eu durmo por um milissegundo no bash ou ksh

107

o sono é um comando muito popular e podemos começar a dormir a partir de 1 segundo:

# wait one second please 
sleep 1

mas qual a alternativa se eu precisar esperar apenas 0,1 segundo ou entre 0,1 e 1 segundo?

  • remark: no linux ou no OS X sleep 0.XXX funciona bem, mas no solaris sleep 0.1 ou sleep 0.01 - sintaxe ilegal
por yael 15.01.2013 / 14:19

6 respostas

59

O Bash tem um sono "carregável" que suporta segundos fracionários e elimina as despesas gerais de um comando externo:

$ cd bash-3.2.48/examples/loadables
$ make sleep && mv sleep sleep.so
$ enable -f sleep.so sleep

Então:

$ which sleep
/usr/bin/sleep
$ builtin sleep
sleep: usage: sleep seconds[.fraction]
$ time (for f in 'seq 1 10'; do builtin sleep 0.1; done)
real    0m1.000s
user    0m0.004s
sys     0m0.004s

A desvantagem é que os carregáveis podem não ser fornecidos com o seu bash binário, então você precisaria compilá-los como mostrado (embora no Solaris isso não seja necessariamente tão simples quanto acima).

A partir de bash-4.4 (setembro de 2016), todos os carregáveis agora são construídos e instalados por padrão nas plataformas que o suportam, embora sejam criados como arquivos separados de objetos compartilhados e sem% sufixo.so. A menos que sua distribuição / sistema operacional tenha feito algo criativo, você deve poder fazer isso:

[ -z "$BASH_LOADABLES_PATH" ] &&
  BASH_LOADABLES_PATH=$(pkg-config bash --variable=loadablesdir 2>/dev/null)  
enable -f sleep sleep

(A página man implica BASH_LOADABLES_PATH é definida automaticamente, acho que este não é o caso na distribuição oficial a partir de 4.4.12. Se e quando estiver configurado corretamente, você precisará apenas de enable -f filename commandname conforme necessário.)

Se isso não for adequado, a próxima coisa mais fácil a fazer é criar ou obter sleep do GNU coreutils, isso suporta o recurso necessário. O comando POSIX sleep é mínima versões mais antigas, o Solaris só isso implementadas. Solaris 11 sleep faz suporte fracionário segundos.

Como último recurso, você pode usar perl (ou qualquer outro script que tenha em mãos) com a ressalva de que a inicialização do intérprete pode ser comparável ao tempo de sono pretendido:

$ perl -e "select(undef,undef,undef,0.1);"
$ echo "after 100" | tclsh
    
por 15.01.2013 / 14:52
105

A documentação do comando sleep de coreutils diz:

Historical implementations of sleep have required that number be an integer, and only accepted a single argument without a suffix. However, GNU sleep accepts arbitrary floating point numbers. See Floating point.

Assim, você pode usar sleep 0.1 , sleep 1.0e-1 e argumentos semelhantes.

    
por 15.01.2013 / 14:22
46

Sleep aceita números decimais para que você possa dividi-lo assim:

1/2 de segundo

 sleep 0.5

1/100 de segundo

sleep 0.01

Então, por um milissegundo, você gostaria de

sleep 0.001
    
por 15.01.2013 / 14:24
11

Tente determinar a precisão:

    time sleep 0.5      # 500 milliseconds (1/2 of a second)
    time sleep 0.001    # 1 millisecond (1/1000 of a second)
    time sleep 1.0      # 1 second (1000 milliseconds)

Combinação da solução do mr.spuratic e solução de coles .

    
por 22.06.2014 / 21:52
6

Você pode simplesmente usar usleep . Leva microssegundos (= 1e-6 segundos) como parâmetro, então, para dormir 1 milissegundo você digitaria:

usleep 1000
    
por 08.07.2015 / 15:55
3

Eu tive o mesmo problema (sem usar shell no Solaris), então escrevi o meu próprio:

  #include "stdio.h"
  int main(int argc, char **argv) {
     if(argc == 1) { usleep(atoi(argv[1])); }
     return 0;
}

Não verifica argumentos - Eu recomendaria um argumento escrito corretamente se você quiser mantê-lo, mas isso (gcc usleep.c -o usleep) irá tirar você de um buraco.

    
por 24.05.2016 / 17:12