web-dev-qa-db-fra.com

Comment obtenir des millisecondes depuis l'époque Unix?

Je veux faire un script bash qui mesure l'heure de lancement d'un navigateur pour cela j'utilise un html qui obtient l'horodatage en charge en millisecondes en utilisant JavaScript.

Dans le script Shell juste avant d'appeler le navigateur, j'obtiens l'horodatage avec:

date +%s

Le problème est qu'il obtient l'horodatage en secondes, et j'en ai besoin en millisecondes car parfois lorsqu'il est exécuté une deuxième fois, le navigateur démarre en moins d'une seconde et je dois pouvoir mesurer ce temps avec précision en utilisant des millisecondes au lieu de secondes.

Comment puis-je obtenir l'horodatage en millisecondes à partir d'un script bash?

32
Eduard Florinescu

date +%s.%N vous donnera, par exemple., 1364391019.877418748. Le% N est le nombre de nanosecondes écoulées dans la seconde actuelle. Remarquez qu'il s'agit de 9 chiffres, et par défaut, la date remplira ceci avec des zéros s'il est inférieur à 100000000. C'est en fait un problème si nous voulons faire des calculs avec le nombre, car bash traite les nombres avec un zéro en tête comme octal . Ce remplissage peut être désactivé en utilisant un trait d'union dans la spécification de champ, donc:

echo $((`date +%s`*1000+`date +%-N`/1000000))

vous donnerait naïvement des millisecondes depuis l'époque.

Cependant , comme le souligne Stéphane Chazelas dans le commentaire ci-dessous, il s'agit de deux appels date différents qui donneront deux temps légèrement différents. Si la seconde est passée entre eux, le calcul sera une seconde entière. Donc:

echo $(($(date +'%s * 1000 + %-N / 1000000')))

Ou optimisé (grâce aux commentaires ci-dessous, bien que cela aurait dû être évident):

echo $(( $(date '+%s%N') / 1000000));
29
goldilocks

Avec le GNU ou l'implémentation ast-open de date (ou busybox 'si construit avec le FEATURE_DATE_NANO option activée), j'utiliserais:

$ date +%s%3N

qui renvoie des millisecondes depuis l'époque Unix.

50
javabeangrinder

Dans le cas où quelqu'un utilise des shells autres que bash, ksh93 Et zsh ont une variable à virgule flottante $SECONDS Si vous faites un typeset -F SECONDS Qui peut être pratique pour mesurer le temps avec précision:

$ typeset -F SECONDS=0
$ do-something
something done
$ echo "$SECONDS seconds have elapsed"
18.3994340000 seconds have elapsed

Depuis la version 4.3.13 (2011) zsh a une variable spéciale à virgule flottante $EPOCHREALTIME Dans le module zsh/datetime:

$ zmodload zsh/datetime
$ echo $EPOCHREALTIME
1364401642.2725396156
$ printf '%d\n' $((EPOCHREALTIME*1000))
1364401755993

Notez que cela est dérivé des deux entiers (pour les secondes et les nanosecondes) renvoyés par clock_gettime(). Sur la plupart des systèmes, c'est plus de précision qu'un seul nombre à virgule flottante C double peut contenir, donc vous perdrez de la précision lorsque vous l'utiliserez dans des expressions arithmétiques (sauf pour les dates des premiers mois de 1970).

$ t=$EPOCHREALTIME
$ echo $t $((t))
1568473231.6078064442 1568473231.6078064

Pour calculer les différences de temps de haute précision (bien que je doute que vous ayez besoin d'une précision supérieure à la milliseconde), vous pouvez utiliser le tableau spécial $epochtime À la place (qui contient les secondes et les nanosecondes comme deux éléments distincts).

Depuis la version 5.7 (2018), le strftime shell intégré prend également en charge un format %N Nanoseconde à la GNU date et un %. pour spécifier la précision, de sorte que le nombre de millisecondes depuis l'époque peut également être récupéré avec:

zmodload zsh/datetime
strftime %s%3. $epochtime

(ou stocké dans une variable avec -s var)

11
Stéphane Chazelas

Pour éviter les calculs pour obtenir les millisecondes, les interprètes JavaScript en ligne de commande peuvent aider:

bash-4.2$ node -e 'console.log(new Date().getTime())' # node.js
1364391220596

bash-4.2$ js60 -e 'print(new Date().getTime())'       # SpiderMonkey
1364391220610

bash-4.2$ jsc -e 'print(new Date().getTime())'        # WebKit 
1364391220622

bash-4.2$ seed -e 'new Date().getTime()'              # GNOME object bridge
1364391220669

Paquets contenant ces interprètes sur Ubuntu Eoan:

8
manatwork

Dans bash 5+, il y a une variable avec une micro-seconde granularité: $EPOCHREALTIME.

Donc:

$ echo "$(( ${EPOCHREALTIME//.} / 1000 ))"
1568385422635

Imprime le temps depuis l'époque (1/1/70) en millisecondes.

A défaut, vous devez utiliser la date. Soit la date GNU:

echo "$(date +'%s%3N')"

L'une des alternatives répertoriées dans https://serverfault.com/a/423642/465827

Ou brew install coreutils pour OS X

Ou, si tout le reste échoue, compilez (gcc epochInµsec.c) ce programme c (ajustez si nécessaire):

#include <stdio.h>
#include <sys/time.h>
int main(void)
{
  struct timeval time_now;
    gettimeofday(&time_now,NULL);
    printf ("%ld secs, %ld usecs\n",time_now.tv_sec,time_now.tv_usec);

    return 0;
}

Notez que l'appel à tout programme externe nécessite du temps pour être lu et chargé à partir du disque, démarré, exécuté et enfin pour imprimer la sortie. Cela prendra plusieurs millisecondes. C'est la précision minimale qui pourrait être obtenue avec n'importe quel outil externe (y compris la date).

3
Isaac