web-dev-qa-db-fra.com

La commande de date ne suit pas les spécifications de Linux (Mac OS X Lion)

Je développe un script sur ma machine Linux depuis un certain temps et je voulais aussi l'exécuter sur mon Mac.

Je pensais que les fonctions sur le Mac étaient les mêmes que celles sur Linux, mais aujourd'hui, j'ai réalisé que c'était faux. Je savais que moins de fonctions existaient sur le Mac, mais je pensais que les fonctions qui existaient avaient la même implémentation.

Ce problème concerne spécifiquement la commande date.

Lorsque j'exécute la commande sur ma machine Linux avec le paramètre permettant de fournir du temps en nanosecondes, le résultat est correct, mais lorsque je l'exécute sur mon mac, il ne dispose pas de cette option.

Linux-Machine> date +%N
55555555555 #Current time in nanoseconds
Mac-Machine> date +%N
N

Comment puis-je obtenir l'heure actuelle en nanosecondes sous forme de commande bash sur Mac?

Le pire cas est que je crée un petit morceau de code qui appelle une fonction système en C ou quelque chose et que je l'appelle ensuite dans mon script.

Toute aide est très appréciée!

47
Kaushik Shankar

En effet, OSX et Linux utilisent deux jeux d’outils différents. Linux utilise la version GNU de la commande date (d'où GNU/Linux). Rappelez-vous que Linux est Linux et OS X est Unix. Ils sont différents.

Vous pouvez installer la commande GNU date incluse dans le paquet "coreutils" à partir de MacPorts . Il sera installé sur votre système sous la forme gdate. Vous pouvez soit utiliser cela, soit lier le binaire date au nouveau binaire gdate; votre choix.

64
JoeLinux

man date indique qu'il ne dépasse pas une seconde. Je recommanderais d'essayer une autre langue:

$ python -c'import time; print repr(time.time())'
1332334298.898616

Ne gémissez pas sous OS X, gémissez sous BSD :-P

8
callumacrae

Il existe des "spécifications Linux" mais elles ne régulent pas beaucoup le comportement de la commande date. Ce que vous avez est vraiment le contraire - Linux (ou plus précisément les outils d'espace utilisateur GNU) possède un grand nombre d'extensions incompatibles avec Unix avec une définition raisonnable.

Il existe un grand nombre de normes qui font réglementent ces choses. Celui que vous devriez regarder est POSIX qui nécessite

date [-u] [+format]

et rien de plus à supporter par les implémentations adhérentes. (Il existe d’autres normes telles que XPG et SUS que vous voudrez peut-être également examiner, mais vous devriez au moins exiger et attendre de POSIX ces jours-ci ... enfin.)

Le document POSIX contient un certain nombre d'exemples mais il n'y a rien pour la date conversion _ qui est cependant un problème pratique pour lequel de nombreux scripts se tournent vers date pour. De plus, pour votre problème concret, rien ne permet de signaler les temps avec une précision inférieure à la seconde dans POSIX.

Quoi qu'il en soit, saisir que * BSD n'est pas Linux n'est pas vraiment utile ici; il vous suffit de comprendre quelles sont les différences et de coder de manière défensive. Si vos exigences sont complexes ou inhabituelles, utilisez un langage de script tel que Perl ou Python, qui effectue ce type de formatage de date plus ou moins prêt à l'emploi dans une installation standard (bien que ni Perl ni Python ne disposent d'un moyen rapide et élégant de ne datez pas {conversion} _ de la boîte, les solutions ont tendance à être un peu torturées).

Concrètement, vous pouvez comparer la page de manuel MacOS date et celle de Linux et essayer de concilier vos exigences.

Pour vos besoins pratiques, MacOS date ne prend en charge aucune chaîne de format avec une précision de l'ordre de la nanoseconde, mais il est peu probable que vous receviez des résultats utiles à cette échelle lorsque l'exécution de la commande prendra un nombre important de nanosecondes. Je me contenterais d'une précision de l'ordre de la milliseconde (et même cela va être gâché par le temps d'exécution dans les derniers chiffres) et je me multiplierais pour obtenir le nombre à l'échelle nanoseconde.

nanoseconds () {
      python -c 'import time; print(int(time.time()*1000*1000*1000))'
}

(Notez les parenthèses entourant l'argument de print() pour Python 3.) Vous remarquerez que Python ne rapporte une valeur avec une précision à la nanoseconde (les derniers chiffres ne sont souvent pas des zéros), bien que vous ayez déjà exécuté time.time() la valeur ne sera évidemment plus correcte.

Pour avoir une idée du taux d'erreur,

bash@macos-high-sierra$ python3
Python 3.5.1 (default, Dec 26 2015, 18:08:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> import timeit
>>> def nanoseconds ():
...   return int(time.time()*1000*1000*1000)
...
>>> timeit.timeit(nanoseconds, number=10000)
0.0066173350023746025
>>> timeit.timeit('int(time.time()*1000*1000*1000)', number=10000)
0.00557799199668807

Les frais généraux de début Python et l'impression de la valeur vont probablement ajouter quelques ordres de grandeur de frais généraux, de manière réaliste, mais je n'ai pas tenté de les quantifier. (La sortie de timeit est en secondes.)

1
tripleee