Frage Wie schlafe ich für eine Millisekunde in Bash oder Ksh


Schlaf ist ein sehr beliebter Befehl und wir können ab 1 Sekunde schlafen:

# wait one second please 
sleep 1

Aber was ist die Alternative, wenn ich nur 0,1 Sekunden oder zwischen 0,1 bis 1 Sekunde warten muss?

  • Bemerkung: unter Linux oder OS X sleep 0.XXX funktioniert gut, aber auf Solaris sleep 0.1 oder sleep 0.01 - Illegale Syntax

105
2018-01-15 13:19


Ursprung


Kann ich fragen, warum Sie für 1ms schlafen möchten? - Tom O'Connor
Ja natürlich, in meinem Bash-Skript füge ich "sleep 1" hinzu, in einigen Zeilen, aber Skript läuft sehr langsam, also nach einigem Schluss kalkuliere ich, dass Schlaf 0.1 auch gute Ergebnisse bringen und schneller. Über die Verzögerung brauche ich Verzögerung in der Reihenfolge Um das SSH-Problem in meinem Bash-Skript zu lösen, führe ich Paralel-SSH-Login auf einigen Rechnern durch und ohne Verzögerung wird es nicht funktionieren. Wie Sie aus meiner Frage wissen, sollte die Verzögerung sowohl Linux als auch Solaris passen - yael
Egal welche Lösung Sie wählen, denken Sie daran, dass ein Shell-Skript in Bezug auf das Timing nicht sehr genau ist. - scai
Wie wäre es mit etwas, das eine sehr kurze Zeit für die Ausführung benötigt, aber nichts tut echo "" >/dev/null - Tom O'Connor
Gute Idee, aber wie msec diesen Befehl nehmen? , Ich brauche 0,1 ms, nicht weniger als das - :) - yael


Antworten:


Bash verfügt über einen "ladbaren" Ruhezustand, der Bruchteile von Sekunden unterstützt und Overheads eines externen Befehls beseitigt:

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

Dann:

$ 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

Der Nachteil ist, dass die Loadables nicht mit Ihrem zur Verfügung gestellt werden können bash binär, also müssten Sie sie wie beschrieben selbst kompilieren (obwohl es bei Solaris nicht unbedingt so einfach wie oben wäre).

Ab bash-4.4 (September 2016) alle ladbaren Dateien werden jetzt standardmäßig auf Plattformen erstellt und installiert, die sie unterstützen, obwohl sie als separate Dateien für gemeinsam genutzte Objekte erstellt wurden und ohne .so Suffix. Sofern Ihre Distribution nichts Kreatives getan hat, sollten Sie stattdessen Folgendes tun können:

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

(Die Manpage impliziert BASH_LOADABLES_PATH wird automatisch gesetzt, ich finde dies in der offiziellen Distribution ab 4.4.12 nicht der Fall. Wenn und wenn es richtig eingestellt ist, brauchen Sie nur enable -f filename commandname nach Bedarf.)

Wenn das nicht passend ist, ist das nächste einfachste Ding zu bauen oder zu erhalten sleep von GNU Coreutils unterstützt dies die erforderliche Funktion. Das POSIX sleep Befehl ist minimal, ältere Solaris-Versionen nur das implementiert. Solaris 11 sleep  tut Unterstützung Bruch Sekunden.

Als letztes Mittel könnten Sie verwenden perl (oder irgendein anderes Skript, das Sie übergeben müssen) mit der Einschränkung, dass die Initialisierung des Interpreters mit der beabsichtigten Schlafzeit vergleichbar sein kann:

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

59
2018-01-15 13:52



Ah, da du es benutzt expect Sie können wahrscheinlich einfach verwenden "after N", wobei N Millisekunden ist, direkt in Ihrem Skript. - mr.spuratic
benutzen usleep wie @Luis Vazquez und @sebix schreiben - Ilan.K


Die Dokumentation für die sleep Befehl von Coreutils sagt:

Historische Implementierungen des Schlafes erfordern, dass diese Zahl ein ist   Ganzzahl und akzeptiert nur ein einzelnes Argument ohne Suffix.   Der GNU-Schlaf akzeptiert jedoch beliebige Fließkommazahlen. Sehen    Gleitkomma.

Daher können Sie verwenden sleep 0.1, sleep 1.0e-1 und ähnliche Argumente.


103
2018-01-15 13:22



Siehe meine Bemerkung zu SOLARIS OS - yael
Hast du dich vermischen? ist und ist nicht? - scai
Siehe mein Update in meiner Version - yael
Yael, ich denke, es gibt immer noch zu viele Negative in deiner Frage. Sind Sie sicher, dass Sie "nicht illegale Syntax" meinen? - MadHatter
zum Beispiel - ich laufe auf Solaris 10 dies: # Schlaf 0,1 Schlaf: schlechter Charakter im Argument, über Linux Schlaf 0,1 funktioniert gut - yael


Sleep akzeptiert Dezimalzahlen, damit Sie es wie folgt aufteilen können:

1/2 Sekunde

 sleep 0.5

1/100 einer Sekunde

sleep 0.01

Also für eine Millisekunde würden Sie wollen

sleep 0.001

46
2018-01-15 13:24



Sie können auch die führende Null vor dem Dezimalpunkt löschen. z.B. sleep .5 - Mike Causer
Ausser für mathforum.org/library/drmath/view/52352.html - stark
Sprechen Sie über alle anderen, die es überkomplizieren ... - Martin


Versuchen Sie dies, um die Genauigkeit zu bestimmen:

    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)

Kombination von mr.kuratics Lösung und Coles Lösung.


11
2018-06-22 19:52





Sie können einfach verwenden usleep. Es dauert Mikrosekunden (= 1e-6 Sekunden) als Parameter, also um 1 Millisekunde zu schlafen würden Sie eingeben:

usleep 1000

6
2017-07-08 13:55



$ usleep  No command 'usleep' found, did you mean:  Command 'sleep' from package 'coreutils' (main)  usleep: command not found - Bulletmagnet
Nein, ich meine usleep Teil der initscripts Paket, das zumindest in allen von Red Hat abgeleiteten Distributionen Standard ist; einschließlich RHEL, CentOS, Fedora, Mageia / Mandriva und SuSE. Hier ein Beispiel: `` `` - Luis Vazquez
Hier ist ein Beispiel, das in CentOS 7 läuft: `` $ $ usleep / usr / bin / usleep $ rpm -qf / usr / bin / usleep initscripts-9.49.37-1.el7_3.1.x86_64 `` `Um zusammenzufassen : - sleep (von Coreutils) arbeitet mit Sekunden - usleep (von Initschriften) arbeitet mit Mikrosekunden - Luis Vazquez


Ich hatte das gleiche Problem (kein Shell-Schlaf auf Solaris) also schrieb ich mein eigenes so:

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

Argumente werden nicht geprüft - ich würde eine korrekt geschriebene Version empfehlen, wenn Sie sie behalten möchten, aber das (gcc usleep.c -o usleep) wird Sie aus einem Loch bringen.


3
2018-05-24 15:12



Du könntest wenigstens ändere das bloß usleep() Aufruf if(argc == 1) { usleep(atoi(argv[1])); } um eine Indexierung außerhalb der Grenzen des Arrays zu vermeiden, was zu einer Anzahl unerwarteter Verhaltensweisen führen kann. - α CVn