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.