Wie bekomme ich die aktuelle Unix-Zeit in Millisekunden in Bash?

232

Wie erhalte ich die aktuelle Unix-Zeit in Millisekunden (dh die Anzahl der Millisekunden seit der Unix-Epoche vom 1. Januar 1970)?

Richard
quelle

Antworten:

265

Diese:

date +%s 

Gibt die Anzahl der Sekunden seit der Epoche zurück.

Diese:

date +%s%N

Gibt die Sekunden und die aktuellen Nanosekunden zurück.

Damit:

date +%s%N | cut -b1-13

gibt die Anzahl der Millisekunden seit der letzten Sekunde plus die drei linken Nanosekunden an.


und von MikeyB - echo $(($(date +%s%N)/1000000))(Division durch 1000 bringt nur Mikrosekunden)

Labyrinth
quelle
39
Ich frage mich, wie viele ms der Schnitt hinzufügt :-)
Kyle Brandt
13
Oder wenn Sie alles in der Shell erledigen möchten, um den teuren Overhead eines zusätzlichen Prozesses zu vermeiden (eigentlich vermeiden wir das Problem, wenn sich die Anzahl der Stellen in% + s + N ändert):echo $(($(date +%s%N)/1000))
MikeyB
5
Es ist das Prinzip der Sache ... vermeide magische Zahlen und Code, was du eigentlich meinst .
MikeyB
25
Ich denke, es ist erwähnenswert, dass der Mann nach Unix und nicht nach Linux gefragt hat und die aktuelle Top-Antwort (Datum +% s% N) auf meinem AIX-System nicht funktioniert.
Pete
12
@Pete +1 Gleiches gilt für OS X und FreeBSD
ocodo
99

Sie können einfach verwenden, %3Num die Nanosekunden auf die drei höchstwertigen Stellen (die dann Millisekunden sind) zu kürzen:

$ date +%s%3N
1397392146866

Das funktioniert zB auf meinem Kubuntu 12.04.

Beachten Sie jedoch, dass %Ndies je nach Zielsystem möglicherweise nicht implementiert ist. ZB getestet auf einem eingebetteten System (buildroot rootfs, kompiliert mit einer nicht-HF Arm Cross Toolchain) gab es keine %N:

$ date +%s%3N
1397392146%3N

(Und auch mein (nicht verwurzeltes) Android-Tablet hat keine %N).

Joe
quelle
1
@warren: Ich sah , dass Sie bearbeitet und verändern das 1397392146%3Nzu 1397392146%N, aber der Ausgang 1397392146%3Nist das , was ich würde auf der Busybox - Konsole meines Android - Tablet wirklich gesehen. Könntest du deine Bearbeitung erklären?
Joe
Der Kommentar von warren aus dem Verlauf wurde von 3 auf 6 geändert, da 3 nur für Mikrosekunden gilt. Seine Bearbeitung scheint völlig falsch zu sein; Sie sollten es zurückrollen.
Bukzor
1
Dies ist eine Funktion von GNU Coreutils. Letztendlich ist dies in gnulib hier implementiert: github.com/gagern/gnulib/blob/… .
Telotortium
wahrscheinlich macht ein Punkt dort Sinn. date +%s.%3Ndruckt 1510718281.134.
Darksky
Dies sollte die akzeptierte Antwort sein.
Noah Sussman
61

date +%N funktioniert nicht unter OS X, aber Sie könnten eines von verwenden

  • Rubin: ruby -e 'puts Time.now.to_f'
  • Python: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • Elixier: DateTime.utc_now() |> DateTime.to_unix(:millisecond)
  • die internets: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • oder für Millisekunden auf die nächste Sekunde gerundet date +%s000
Lri
quelle
1
Der Vollständigkeit node -e 'console.log(Date.now())'
halber
1
Verwendung von PHP:php -r 'echo microtime(TRUE);'
TachyonVortex
8
Klar, Sie müssen nur warten, bis sich die Dolmetscher aufgewärmt haben. Dies funktioniert auch:wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
Camilo Martin
8
Oder, wenn Sie eigentlich nicht die Millisekunden brauchen, sondern nur das richtige Format:date +%s000
Lenar Hoyt
1
apple.stackexchange.com/questions/135742/… hat Anweisungen dazu in OSX über Brew'scoreutils
sameers 17.11.17
9

Wirf das einfach raus, aber ich denke, die richtige Formel mit der Aufteilung wäre:

echo $(($(date +%s%N)/1000000))
splattne
quelle
9

Meine Lösung ist nicht die beste, hat aber für mich funktioniert.

date +%s000

Ich musste nur ein Datum wie den 05.05.2012 in Millisekunden umrechnen.

Pablo
quelle
1
Amazing Hack, lol :)
k06a
7
Sie müssen jemand unter meinen Mitarbeitern sein.
Nakilon
7

Für die Leute, die vorschlagen, externe Programme auszuführen , um die Millisekunden zu erhalten ... in diesem Tempo können Sie auch Folgendes tun:

wget -qO- http://www.timeapi.org/utc/now?\\s.\\N

Beachten Sie, dass nicht alle Programme unter einer Sekunde ausgeführt werden, bevor Sie hier eine Antwort eingeben. Messen!

Camilo Martin
quelle
Sie fragen das lokale System nicht nach der Zeit. Was ich denke, ist in der Frage impliziert. Sie sind auch auf eine Netzwerkverbindung angewiesen.
Orkoden
2
@orkoden Die Frage fragt explizit nach "Anzahl der Millisekunden seit der Unix-Epoche 1. Januar 1970". Außerdem möchte ich Sie darauf hinweisen, dass Sie niemals ganz Ruby oder Python (oder wget) starten sollten, um die Zeit zu gewinnen. Entweder geschieht dies über einen schnellen Kanal, oder Millisekunden spielen keine Rolle.
Camilo Martin
2
Ja, ich habe verstanden, dass Sie eine schlechtere Lösung angegeben haben, um die Mängel der schlechten Lösung hervorzuheben. Ich habe mehrere Lösungen ausprobiert und die Zeit gemessen. lpaste.net/119499 Die Ergebnisse sind irgendwie interessant. Selbst auf einer sehr schnellen i7-Maschine datedauert die Ausführung 3 ms.
Orkoden
@orkoden Schöne Tests! Welches Betriebssystem? Dies kann mit dem Prozess-Spawning-Overhead zusammenhängen.
Camilo Martin
1
@Nakilon und aus diesem Grund sollte man sich bei der Produktion nicht auf kräuselbare Annehmlichkeiten wie diese verlassen.
Camilo Martin
4

Diese Lösung funktioniert unter MacOS.

Wenn Sie ein Bash-Skript verwenden und Python zur Verfügung haben, können Sie diesen Code verwenden:

#!/bin/bash

python -c 'from time import time; print int(round(time() * 1000))'
Frank Thonig
quelle
warum stimmen die ab?
Frank Thonig
Scheint nicht besonders gerechtfertigt. Der Hinweis auf den Abwärtspfeil lautet "Diese Antwort ist nicht nützlich", aber IMO ist es nützlich. Vielleicht wollten sie, dass Sie es stattdessen zu einem Python-Skript machen. Das wäre einfacher und würde auch gut als Bash-Befehl funktionieren.
Andrew Schulman
Sorgen Sie sich nicht zu sehr um Abstimmungen (es war nicht meine) ... besonders wenn sie anonym sind (woraus man nicht lernen kann, was falsch zu sein scheint, oder?). Nur um zu sehen, wie du es verarbeitest ... hier ist noch eine +1 ... rate mal was: DU darfst jetzt auch "abstimmen", oder?
Pierre.Vriens
Die Ablehnung scheint durch ein Problem mit dem System verursacht worden zu sein. Es wurde seitdem wieder vom System entfernt.
Michael Hampton
2

Wenn Sie nach einer Möglichkeit suchen, die Ausführungsdauer Ihres Skripts anzuzeigen, erhalten Sie mit den folgenden Angaben ein (nicht ganz genaues) Ergebnis:

Geben Sie so nah wie möglich am Anfang Ihres Skripts Folgendes ein

basetime=$(date +%s%N)

Dies gibt Ihnen einen Startwert von 1361802943996000000

Verwenden Sie am Ende Ihres Skripts Folgendes

echo "runtime: $(echo "scale=3;($(date +%s%N) - ${basetime})/(1*10^09)" | bc) seconds"

das wird so etwas wie anzeigen

runtime: 12.383 seconds

Anmerkungen:

(1 * 10 ^ 09) kann auf Wunsch durch 1000000000 ersetzt werden

"scale=3"ist eine eher seltene Einstellung, die dazu zwingt, das bczu tun, was Sie wollen. Es gibt noch viel mehr!

Ich habe dies nur unter Win7 / MinGW getestet ... Ich habe keine richtige * nix-Box zur Hand.

user161733
quelle
3
oder Sie könnten einfach verwendentime <script>
Warren
2

So erhalten Sie Zeit in Millisekunden, ohne eine Division durchzuführen. Vielleicht ist es schneller ...

# test=`date +%s%N`
# testnum=${#test}
# echo ${test:0:$testnum-6}
1297327781715

Update: Eine weitere Alternative in Pure Bash, die nur funktioniert, bash 4.2+ist die gleiche wie oben, wird jedoch verwendet printf, um das Datum abzurufen. Es wird auf jeden Fall schneller sein, da keine Prozesse von dem Hauptprozess abgezweigt werden.

printf -v test '%(%s%N)T' -1
testnum=${#test}
echo ${test:0:$testnum-6}

Ein weiterer Haken dabei ist, dass Ihre strftimeImplementierung dies unterstützen sollte %sund %Nwas auf meinem Testcomputer NICHT der Fall ist. Siehe man strftimeunterstützte Optionen. Siehe auch man bashsehen printfSyntax. -1und -2sind spezielle Werte für die Zeit.

akostadinov
quelle
Scheint so, als ob meine strftime(3)keine Unterstützung %Nfür printfdas Drucken von Nanosekunden bietet . Ich benutze Ubuntu 14.04.
Haridsv
@haridsv, ja, es ist nicht in glibc. datescheint wie die zuverlässigere Option.
Akostadinov
2

Der genaueste Zeitstempel, den wir bekommen können (zumindest für Mac OS X), ist wahrscheinlich der folgende:

python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")'

1490665305.021699

Wir müssen jedoch berücksichtigen, dass die Ausführung etwa 30 Millisekunden dauert. Wir können es auf die Skala eines 2-stelligen Bruchteils zuschneiden und ganz zu Beginn den durchschnittlichen Aufwand für das Ablesen der Zeit berechnen und es dann von der Messung entfernen. Hier ist ein Beispiel:

function getTimestamp {
  echo `python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")' | cut -b1-13` 
}
function getDiff {
  echo "$2-$1-$MeasuringCost" | bc
}
prev_a=`getTimestamp`
acc=0
ITERATIONS=30
for i in `seq 1 $ITERATIONS`;do 
  #echo -n $i 
  a=`getTimestamp`
  #echo -n "   $a"
  b=`echo "$a-$prev_a" | bc`
  prev_a=$a
  #echo "  diff=$b"
  acc=`echo "$acc+$b" | bc`
done
MeasuringCost=`echo "scale=2; $acc/$ITERATIONS" | bc`
echo "average: $MeasuringCost sec"
t1=`getTimestamp`
sleep 2
t2=`getTimestamp`
echo "measured seconds: `getDiff $t1 $t2`"

Sie können die Echobefehle auskommentieren, um besser zu sehen, wie es funktioniert.

Die Ergebnisse für dieses Skript sind normalerweise eines der folgenden 3 Ergebnisse:

measured seconds: 1.99
measured seconds: 2.00
measured seconds: 2.01
ishahak
quelle
1

Mit date und expr können Sie dorthin gelangen, z

X=$(expr \`date +%H\` \\* 3600 + \`date +%M\` \\* 60 + \`date +%S\`)
echo $X

Erweitern Sie es einfach, um zu tun, was Sie wollen

Mir ist klar, dass dies seit der Epoche keine Millisekunden mehr sind, aber in einigen Fällen kann es dennoch nützlich sein, es hängt davon ab, wofür Sie es wirklich benötigen. Multiplizieren Sie es mit 1000, wenn Sie eine Millisekunden-Zahl benötigen: D

Am einfachsten wäre es, eine kleine ausführbare Datei (aus C f.ex.) zu erstellen und sie dem Skript zur Verfügung zu stellen.

Johan Andersson
quelle
Möglicherweise tritt ein Problem datemehrmals auf. In einigen Fällen können sich Datum und Uhrzeit zwischen den Ausführungen ändern, während Ihr Befehl geschrieben wird. Es ist besser, dateeinmal zu starten, die Teile zu analysieren und Ihre Berechnung durchzuführen. Eine von mehreren Möglichkeiten, dies zu tun, wäre t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x". Hierbei wird die Bash-Syntax verwendet, da die Frage mit bash gekennzeichnet ist . Wie Sie anspielen, gibt Ihre Antwort (und meine Variante) bisher nur Sekunden für den aktuellen Tag und nicht seit der Epoche und nicht in Millis.
Dennis Williamson
1

(von oben wiederholen) date +%N funktioniert nicht unter OS X, aber Sie könnten auch Folgendes verwenden:

Perl (erfordert das Time :: Format-Modul). Möglicherweise nicht das beste zu verwendende CPAN-Modul, erledigt aber die Aufgabe. Time :: Format wird in der Regel mit Distributionen zur Verfügung gestellt.

perl -w -e'use Time::Format; printf STDOUT ("%s.%s\n", time, $time{"mmm"})'
TVNshack
quelle
Das OP fragte ausdrücklich nach Möglichkeiten, dies mit bash zu tun. Wie ist diese Bash, als Methode speichern, um etwas anderes zu starten?
MadHatter
Ich benutze dies in meinen Bash-Shell-Skripten ... unter OSX. So datekann nicht verwendet werden , und es gibt keine bash-nur Befehle , die die Notwendigkeit beantworten.
TVNshack
Fair genug. Wenn Sie klarstellen möchten , warum OSX datenicht als Teil Ihrer Antwort verwendet werden kann , würde ich meine Ablehnung entfernen.
MadHatter
Dies wurde ein paar Antworten oben erklärt. Ich konnte den Befehl, der in der vorgeschlagenen Liste fehlte, nicht als Kommentar hinzufügen. Also habe ich es hier hinzugefügt.
TVNshack
Fairerweise akzeptiere ich, dass dies eine nützliche Ergänzung zum Kanon ist. +1 von mir!
MadHatter
1

Alle vorherigen Antworten in OSX zusammenfassen

ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G31+

Sie können gerne tun

microtime() {
    python -c 'import time; print time.time()'
}
compute() {
    local START=$(microtime)
    #$1 is command $2 are args
    local END=$(microtime)
    DIFF=$(echo "$END - $START" | bc)
    echo "$1\t$2\t$DIFF"
}
loretoparisi
quelle
0

Wenn Sie eine einfache Berechnung der abgelaufenen Shell wünschen, ist dies einfach und portierbar. Verwenden Sie dazu die obige Antwort:

now() {
    python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")'
}
seismo:~$ x=`now`
seismo:~$ y=`now`
seismo:~$ echo "$y - $x" | bc
5.212514
Bill Cheswick
quelle
0

Für alpines Linux (viele Docker-Images) und möglicherweise andere minimale Linux-Umgebungen können Sie Folgendes missbrauchen adjtimex:

adjtimex | awk '/(time.tv_usec):/ { printf("%06d\n", $2) }' | head -c3

adjtimexwird zum Lesen (und Setzen) von Kernel-Zeitvariablen verwendet. Mit awkkönnen Sie die Mikrosekunden erhalten, mit können headSie nur die ersten 3 Stellen verwenden.

Ich habe keine Ahnung, wie zuverlässig dieser Befehl ist.

Hinweis: Schamlos aus dieser Antwort gestohlen

Qw3ry
quelle