Como durmo um milissegundo em bash ou ksh


128

sleep é 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 a 1 segundo?

  • observação: no linux ou no OS X sleep 0.XXXfunciona bem, mas no solaris sleep 0.1ou sleep 0.01- sintaxe ilegal

2
Posso perguntar por que você quer dormir por 1ms?
Tom O'Connor

1
Sim, é claro, no meu script bash eu adiciono "sleep 1", em algumas linhas, mas o script é executado muito lentamente, então, após alguma conclusão, calculo que o sleep 0.1 também trará bons resultados e mais rápido Sobre o atraso, preciso de um atraso para para resolver o problema ssh no meu script bash, eu executo o login ssh paralelo para algumas máquinas de esperar e sem demora o seu não vai funcionar, Como você sabe da minha pergunta o atraso deve caber Linux e Solaris
yael

3
Qualquer que seja a solução que você escolher, lembre-se de que um script de shell não será muito preciso em termos de tempo.
Scai

Que tal fazer algo que leva um tempo muito curto para ser executado, mas não faz nada .. comoecho "" >/dev/null
Tom O'Connor

Boa ideia, mas como msec este comando leva? , Eu preciso de 0,1 ms, e não menos, então, que - :)
yael

Respostas:


68

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 bashbinário, portanto você precisará compilá-los como mostrado (embora no Solaris não seja necessariamente tão simples como acima).

A partir debash-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 construídos como arquivos de objetos compartilhados separados e sem .sosufixo. A menos que sua distribuição / SO tenha feito algo criativo, você poderá fazer:

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

(A página de manual implica que ela BASH_LOADABLES_PATHseja configurada automaticamente, acho que esse não é o caso na distribuição oficial a partir de 4.4.12. Se e quando estiver configurada corretamente, você precisará apenas enable -f filename commandnameconforme necessário.)

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

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

2
Ah, como você está usando, expectprovavelmente pode usar " after N", onde N é milissegundos, diretamente no seu script.
precisa saber é o seguinte

usar usleepcomo @Luis Vazquez e escrever @sebix
Ilan.K

Apple MacOS tem suspensão BSD, que também suporta segundos fracionários
roblogic

125

A documentação para o sleepcomando do coreutils diz:

As implementações históricas do sono exigiram que o número fosse um número inteiro e só aceitaram um único argumento sem sufixo. No entanto, o sono GNU aceita números arbitrários de ponto flutuante. Consulte Ponto flutuante .

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


1
veja minha observação sobre o SOLARIS OS
yael

Você misturou é e não é ?
Scal

veja minha atualização no meu quastion
yael

1
Yael, acho que ainda há muitos pontos negativos na sua pergunta; tem certeza de que quer dizer "sintaxe não ilegal"?
MadHatter

por exemplo - eu corro no solaris 10 isto: # sono 0.1 sono: caractere ruim no argumento, sobre o sono linux 0.1 funciona bem
yael

58

O modo de suspensão aceita números decimais para que você possa decompô-lo da seguinte maneira:

1/2 de segundo

 sleep 0.5

1/100 de segundo

sleep 0.01

Então, por um milissegundo, você gostaria

sleep 0.001

4
Você também pode soltar o zero inicial antes do ponto decimal. por exemplo. sleep .5
Mike Causador


Fale sobre todos os outros complicar-lo ...
Martin

1
Os zeros à esquerda do @MikeCauser são muito mais legíveis e sinalizam a intenção para o leitor do código posteriormente. também melhor quando você realmente faz contas.
Alexander Mills


8

Você pode simplesmente usar usleep. Leva microssegundos (= 1e-6 segundos) como parâmetro; portanto, para dormir 1 milissegundo, você deve digitar:

usleep 1000

1
$ usleep No command 'usleep' found, did you mean: Command 'sleep' from package 'coreutils' (main) usleep: command not found
Bulletmagnet

Não, quero dizer usleepparte do initscriptspacote, que é padrão pelo menos em todas as distribuições derivadas da Red Hat; incluindo pelo menos RHEL, CentOS, Fedora, Mageia / Mandriva e SuSE. Aqui está um exemplo: `` ``
Luis Vazquez

1
Aqui está uma ilustração de exemplo em execução no CentOS 7: `` $ what usleep / usr / bin / usleep $ rpm -qf / usr / bin / usleep initscripts-9.49.37-1.el7_3.1.x86_64 `` `Para resumir : - sleep(do coreutils ) trabalha com segundos - usleep(do initscripts ) trabalha com micro segundos
Luis Vazquez

4

Eu tive o mesmo problema (sem uso de shell no Solaris), então escrevi o meu da seguinte maneira:

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

Não verifica argumentos - eu recomendaria um escrito corretamente se você quisesse mantê-lo, mas que (gcc usleep.c -o usleep) o tirará de um buraco.


1
Você pode pelo menos alterar essa usleep()chamada simples if(argc == 1) { usleep(atoi(argv[1])); }para evitar a indexação fora dos limites da matriz, o que pode levar a qualquer número de comportamentos inesperados.
um CVn

@aCVn Na verdade é if (argc == 2) { usleep(atoi(argv[1])); }...
Anel Ø

Observe também que a usleepunidade é μs; portanto, para aguardar 1 segundo, é necessário fornecer um argumento 1000000.
Anel Ø

@ RingØ Certo. Erro estúpido, boa captura.
um CVn 26/03

atoi()é uma escolha horrível para converter uma string em um int. O que atoi( "STRING" )retorna? atoi()não tem como retornar nenhum erro.
Andrew Henle

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.