Jak spać przez milisekundę w bash lub ksh


128

sen jest bardzo popularnym poleceniem i możemy zacząć spać od 1 sekundy:

# wait one second please 
sleep 1

ale jaka alternatywa, jeśli muszę czekać tylko 0,1 sekundy lub od 0,1 do 1 sekundy?

  • Uwaga: na Linuksie lub OS X sleep 0.XXXdziała dobrze, ale na Solaris sleep 0.1lub sleep 0.01- Nielegalna składnia

2
Czy mogę zapytać, dlaczego chcesz spać przez 1ms?
Tom O'Connor,

1
Tak, oczywiście, w moim skrypcie bash dodałem „sleep 1”, w niektórych liniach, ale skrypt działa bardzo wolno, więc po pewnych wnioskach obliczyłem, że sen 0.1 przynosi również dobre wyniki i jest szybszy O opóźnieniu potrzebuję opóźnienia aby rozwiązać problem ssh w moim skrypcie bash, wykonuję równoległe logowanie ssh do niektórych maszyn przez oczekiwanie i bezzwłocznie jego nie zadziała, jak wiecie z mojego pytania, opóźnienie powinno pasować zarówno do Linuksa, jak i do Solaris
yael

3
Niezależnie od wybranego rozwiązania pamiętaj, że skrypt powłoki nie będzie zbyt dokładny pod względem czasu.
scai 15.01.2013

Co powiesz na zrobienie czegoś, co wymaga bardzo krótkiego czasu, ale nic nie robi ... jakecho "" >/dev/null
Tom O'Connor

Dobry pomysł, ale jak msc to polecenie? , Potrzebuję 0,1 ms, nie mniej niż to - :)
yael

Odpowiedzi:


68

Bash ma „ładowany” sen, który obsługuje ułamkowe sekundy i eliminuje koszty zewnętrzne polecenia:

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

Następnie:

$ 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

Minusem jest to, że pliki ładowalne mogą nie być dostarczane z Twoim bashplikiem binarnym, więc musisz sam je skompilować, jak pokazano (chociaż w Solarisie nie musi to być tak proste, jak powyżej).

Odbash-4.4 (wrzesień 2016 r.) Wszystkie programy ładujące są teraz budowane i instalowane domyślnie na platformach, które je obsługują, chociaż są one budowane jako osobne pliki obiektów współużytkowanych i bez .soprzyrostka. O ile Twój system / system operacyjny nie zrobił czegoś kreatywnego, powinieneś być w stanie to zrobić:

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

(Strona BASH_LOADABLES_PATHpodręcznika sugeruje, że jest ustawiana automatycznie, uważam, że nie jest tak w oficjalnej dystrybucji od 4.4.12. Jeśli i kiedy jest ustawiona poprawnie, potrzebujesz tylko enable -f filename commandnamezgodnie z wymaganiami.)

Jeśli to nie jest odpowiednie, następną najłatwiejszą rzeczą jest zbudowanie lub uzyskanie sleepz GNU coreutils, obsługuje to wymaganą funkcję. Polecenie POSIX sleepjest minimalne, starsze wersje systemu Solaris zaimplementowały tylko to. Solaris 11 sleep nie obsługują ułamków sekund.

W ostateczności możesz użyć perl(lub dowolnego innego skryptu, który masz pod ręką) z zastrzeżeniem, że inicjowanie interpretera może być porównywalne z zamierzonym czasem snu:

$ perl -e "select(undef,undef,undef,0.1);"
$ echo "after 100" | tclsh

2
Ach, skoro używasz expect, prawdopodobnie możesz po prostu użyć „ after N”, gdzie N to milisekundy, bezpośrednio w skrypcie.
mr. Spuratic

użyj usleepjak @Luis Vazquez i @sebix pisz
Ilan.K

Apple MacOS ma
tryb

125

Dokumentacja sleeppolecenia z coreutils mówi:

Historyczne implementacje uśpienia wymagały, aby liczba ta była liczbą całkowitą i zaakceptowała tylko jeden argument bez przyrostka. Jednak GNU sleep akceptuje dowolne liczby zmiennoprzecinkowe. Zobacz zmiennoprzecinkowy .

Stąd można użyć sleep 0.1, sleep 1.0e-1i podobne argumenty.


1
zobacz moją uwagę na temat systemu operacyjnego SOLARIS
yael 15.01.13

Czy mieszać to i nie jest ?
scai

zobacz moją aktualizację w moim
pytaniu

1
Yael, myślę, że w twoim pytaniu wciąż jest za dużo negatywów; czy na pewno masz na myśli „nie nielegalną składnię”?
MadHatter

na przykład - uruchamiam na solaris 10 to: # sen 0,1 sen: zły znak w kłótni, o linux sen 0,1 działa dobrze
yael

58

Tryb uśpienia akceptuje liczby dziesiętne, dzięki czemu możesz go podzielić w następujący sposób:

1/2 sekundy

 sleep 0.5

1/100 sekundy

sleep 0.01

Więc przez milisekundę chciałbyś

sleep 0.001

4
Możesz także upuścić wiodące zero przed przecinkiem. na przykład. sleep .5
Mike Causer


Porozmawiaj o tym, że wszyscy to komplikują ...
Martin

1
@MikeCauser wiodące zera są znacznie bardziej czytelne i sygnalizują zamiar czytelnikowi kodu później. także lepiej, kiedy faktycznie robisz matematykę.
Alexander Mills,


8

Możesz po prostu użyć usleep. Jako parametr potrzeba mikrosekund (= 1e-6 sekund), więc aby spać 1 milisekundę, wpisz:

usleep 1000

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

Nie, mam na myśli usleepczęść initscriptspakietu, która jest standardowa przynajmniej we wszystkich dystrybucjach pochodzących od Red Hata; w tym co najmniej RHEL, CentOS, Fedora, Mageia / Mandriva i SuSE. Oto przykład: ``
Luis Vazquez

1
Oto przykładowa ilustracja uruchomiona w CentOS 7: `` $ usleep / usr / bin / usleep $ rpm -qf / usr / bin / usleep initscripts-9.49.37-1.el7_3.1.x86_64 `` Podsumowując : - sleep(z coreutils ) działa z sekundami - usleep(z skryptów startowych ) działa z mikro-sekundami
Luis Vazquez

4

Miałem ten sam problem (brak snu w Solarisie), więc napisałem swój w ten sposób:

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

Nie sprawdza argumentów - polecam poprawnie napisany, jeśli chcesz go zachować, ale to (gcc usleep.c -o usleep) wyciągnie cię z dziury.


1
Możesz przynajmniej zmienić to puste usleep()połączenie, aby if(argc == 1) { usleep(atoi(argv[1])); }uniknąć indeksowania poza granicami tablicy, co może prowadzić do dowolnej liczby nieoczekiwanych zachowań.
CVn

@aCVn To właściwie if (argc == 2) { usleep(atoi(argv[1])); }...
Pierścień Ø

Zauważ też, że usleepjednostką jest μs, więc aby poczekać 1 sekundę, musisz podać argument 1000000.
Pierścień Ø

@ Pierścień Ø Prawo. Głupi błąd, dobry chwyt.
CVn

atoi()jest okropnym wyborem do konwersji łańcucha na int. Co atoi( "STRING" )zwraca atoi()nie ma możliwości zwrócenia żadnego błędu.
Andrew Henle

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.