Comment puis-je dormir pendant une milliseconde en bash ou en ksh

128

Le sommeil est une commande très populaire et nous pouvons commencer à dormir à partir de 1 seconde:

# wait one second please 
sleep 1

mais quelle est l'alternative si je dois attendre seulement 0,1 seconde ou entre 0,1 et 1 seconde?

  • remarque: sous Linux ou OS X sleep 0.XXXfonctionne bien, mais sous Solaris sleep 0.1ou sleep 0.01- syntaxe illégale
yael
la source
2
Puis-je demander pourquoi vous voulez dormir pendant 1ms?
Tom O'Connor
1
Oui bien sûr, dans mon script bash j'ajoute "sleep 1", dans certaines lignes, mais le script s'exécute très lentement, donc après quelques conclusions, je calcule que sleep 0.1 apporte également de bons résultats et plus rapidement À propos du délai, j'ai besoin de délai dans l'ordre pour résoudre le problème ssh dans mon script bash, j'effectue une connexion ssh paralel certaines machines par attendre et sans délai son ne fonctionnera pas, Comme vous le savez de ma question le délai doit adapter à la fois Linux et Solaris
yael
3
Quelle que soit la solution choisie, gardez à l'esprit qu'un script shell ne sera pas très précis en termes de timing.
Scai
Que diriez-vous de faire quelque chose qui prend très peu de temps à exécuter, mais ne fait rien .. commeecho "" >/dev/null
Tom O'Connor
Bonne idée mais comment msec cette commande prend? , J’ai besoin de 0,1 ms, pas moins que ça - :)
yael

Réponses:

68

Bash a un sommeil "chargeable" qui prend en charge une fraction de seconde et élimine les frais généraux d'une commande externe:

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

Ensuite:

$ 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

L'inconvénient est que les éléments chargeables ne peuvent pas être fournis avec votre bashfichier binaire, vous devez donc les compiler vous-même, comme indiqué (bien que sous Solaris, ce ne soit pas nécessairement aussi simple que ci-dessus).

Depuisbash-4.4 septembre 2016, tous les objets chargeables sont désormais construits et installés par défaut sur les plates-formes qui le prennent en charge, bien qu'ils soient générés sous la forme de fichiers à objets partagés séparés et sans .sosuffixe. À moins que votre distribution / votre système d’exploitation n’ait fait quelque chose de créatif, vous devriez pouvoir le faire:

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

(La page de manuel implique que le BASH_LOADABLES_PATHréglage est automatique, je constate que ce n'est pas le cas dans la distribution officielle à partir de la version 4.4.12. Si et quand il est correctement défini, vous n'aurez besoin que de la enable -f filename commandnamemanière requise.)

Si cela ne convient pas, la prochaine chose à faire est de créer ou d’obtenir sleepGNU coreutils, ceci prend en charge la fonctionnalité requise. La sleepcommande POSIX est minimale, les anciennes versions de Solaris ne l'implémentant que. Solaris 11 sleep prend en charge les secondes fractionnelles.

En dernier recours, vous pouvez utiliser perl(ou tout autre script que vous avez sous la main) en précisant que l'initialisation de l'interpréteur peut être comparable au temps de sommeil souhaité:

$ perl -e "select(undef,undef,undef,0.1);"
$ echo "after 100" | tclsh
mr.spuratic
la source
2
Ah, puisque vous utilisez, expectvous pouvez probablement simplement utiliser " after N", où N est millisecondes, directement dans votre script.
mr.spuratic
utiliser usleepcomme @Luis Vazquez et @sebix write
Ilan.K 20/02/2016
Apple MacOS a un sommeil BSD, qui prend également en charge des fractions de secondes
roblogic
125

La documentation de la sleepcommande de coreutils indique:

Les mises en œuvre historiques de sommeil ont requis que ce nombre soit un entier et n'accepte qu'un seul argument sans suffixe. Cependant, GNU sleep accepte des nombres à virgule flottante arbitraires. Voir à virgule flottante .

Par conséquent , vous pouvez utiliser sleep 0.1, sleep 1.0e-1et des arguments similaires.

scai
la source
1
voir ma remarque à propos de SOLARIS OS
yael
Avez-vous confondu est et n'est pas ?
scai
voir ma mise à jour dans ma quastion
yael
1
Yael, je pense qu'il y a encore trop de points négatifs dans votre question. Êtes-vous sûr de vouloir dire "syntaxe non illégale"?
MadHatter
par exemple - je cours sur solaris 10 ceci: # sommeil 0.1 sommeil: mauvais personnage en argument, à propos de linux sommeil 0,1 fonctionne très bien
yael
58

Sleep accepte les nombres décimaux afin que vous puissiez le décomposer comme ceci:

1/2 de seconde

 sleep 0.5

1/100 de seconde

sleep 0.01

Donc, pendant une milliseconde, vous voudriez

sleep 0.001
colealtdelete
la source
4
Vous pouvez également supprimer le zéro avant le point décimal. par exemple. sleep .5
Mike Causer
Parlez de tous les autres trop compliquer les choses ...
Martin
1
@MikeCauser menant des zéros beaucoup plus lisible et signalant l'intention au lecteur du code plus tard. également mieux lorsque vous faites des mathématiques.
Alexander Mills
11

Essayez ceci pour déterminer la précision:

    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)

Combinaison de la solution de mr.spuratic et de la solution de coles .

dsrdakota
la source
8

Vous pouvez simplement utiliser usleep. Cela prend microsecondes (= 1e-6 secondes) en paramètre, donc pour dormir 1 milliseconde, vous devez entrer:

usleep 1000
Luis Vazquez
la source
1
$ usleep No command 'usleep' found, did you mean: Command 'sleep' from package 'coreutils' (main) usleep: command not found
Bulletmagnet
Non, je veux dire une usleeppartie du initscriptspaquet qui est standard au moins dans toutes les distributions dérivées de Red Hat; incluant au moins RHEL, CentOS, Fedora, Mageia / Mandriva et SuSE. Voici un exemple: `` ``
Luis Vazquez
1
Voici un exemple d’illustration sous CentOS 7: `` $ $ usleep / usr / bin / usleep $ rpm -qf / usr / bin / usleep initscripts-9.49.37-1.el7_3.1.x86_64 `` `Pour résumer : - sleep(de coreutils ) fonctionne avec des secondes - usleep(de initscripts ) fonctionne avec des microsecondes
Luis Vazquez
4

J'ai eu le même problème (pas de shell usleep sur Solaris) alors j'ai écrit le mien ainsi:

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

Ne vérifie pas les arguments - je vous en recommanderais un bien écrit si vous voulez le conserver, mais que (gcc usleep.c -o usleep) vous sortira d'un trou.

Jrichemont
la source
1
Vous pouvez au moins changer cet usleep()appel à nu if(argc == 1) { usleep(atoi(argv[1])); }pour éviter l'indexation en dehors des limites du tableau, ce qui peut entraîner un certain nombre de comportements inattendus.
un CVn
@aCVn C'est en fait if (argc == 2) { usleep(atoi(argv[1])); }...
Bague Ø
Notez également que l' usleepunité est μs, donc pour attendre 1 seconde, vous devez fournir un argument 1000000.
Anneau Ø
@ RingØ Droite. Erreur stupide, bonne prise.
un CVn
atoi()est un choix horrible pour convertir une chaîne en un int. Qu'est-ce que atoi( "STRING" )retourne? atoi()n'a aucun moyen de retourner une erreur.
Andrew Henle