Wie finde ich die Gesamtzeit, die ich in diesem Jahr auf meinem Laptop verbracht habe?

17

Ich möchte wissen, wie viel Zeit ich im Jahr 2016 mit der Arbeit an meinem Laptop verbracht habe.

last reboot --since 2016-01-01 --until 2016-12-31 | grep -o '(.*)' | grep  -v '-'

gibt mir die Gesamtverfügbarkeit des Laptops in diesem Format:

(01:33) 
(04:40) 
(01:31) 
(1+06:41) 
(02:47) 
(00:30)

Wie rechne ich das jetzt zusammen?

daltonfury42
quelle
Kannst du mir die Bedeutung von (1 + 06: 41) sagen?
kashish
@kashish 1 Tag, 6 Stunden, 41 Minuten
muru
Die Sache ist, dass wtmpProtokolle (was Sie in der Ausgabe des lastBefehls sehen) so eingestellt sind, dass sie monatlich (in /etc/logrotate.conf) rotieren , was bedeutet, dass nach einer bestimmten Zeitspanne das älteste Protokoll gelöscht wird. Mit anderen Worten, was auch immer Sie versuchen last, es wird nicht genau sein
Sergiy Kolodyazhnyy
@ Serg Ich habe Logrotate für wtmp deaktiviert. Es ist mehr als ein Jahr her, seit ich das getan habe, und die Dateigröße beträgt derzeit 3,7 MB. Ich sehe also keinen Grund, warum es monatlich gewechselt werden sollte. ;)
daltonfury42
@ daltonfury42 Wenn es deaktiviert ist, dreht es sich nicht. Die meisten Benutzer tun das nicht.
Sergiy Kolodyazhnyy

Antworten:

5

Hier ist eine awk + awk Version:

last ... | awk '/reboot/{print $NF}' |
    awk -F '[(+:)]' '
        {
            d += $(NF - 3); h += $(NF - 2); m += $(NF - 1)
        }
        END {
            carry = m / 60; h += carry;
            carry = h / 24; d += carry;
            printf "%d days, %d hours, %d minutes\n", d, h % 24, m % 60
        }'

last‚s letzte Spalte ist in dem Format (<days>+hours:minutes), in dem days+fallen gelassen wird , wenn der Zeitraum weniger als 1 Tag.

Hier gibt der erste awkBefehl die letzte Spalte, die Dauer des Interesses, für rebootEinträge aus.

Für den zweiten awkBefehl:

  1. FSist [(+:)], dh, Klammern oder + oder : . So (h:m)ist Split , h, mund (erste und letzte Felder leer), und (d+h:m)ist gespalten zu , d, h, mund (wieder erste und letzte Felder leer).
  2. Dann nehmen wir das vorletzte Feld für Minuten, das drittletzte für Stunden und das viertletzte für Tage. Das viertletzte Feld ist das erste, leere Feld, wenn keine Tage vorhanden sind. Also werden wir 0in diesem Fall einfach hinzufügen .
  3. Dann erhöhen wir die Stunden und Tage um, wenn die Minuten und Stunden über 60 bzw. 24 liegen. Beachten Sie, dass awk eine Gleitkommadivision durchführt hund dnun möglicherweise Bruchteile enthält.
  4. Dann drucken wir die Zahlen als ganze Zahlen ( %d), sodass jeder Bruchteil ignoriert wird.
muru
quelle
8

Versuchen Sie es mit Bash-Skript und erweitern Sie Ihren Befehl. Ich dateutilsaddiere die Zeitdauer.

Zur Verwendung dieses Skripts ist daher das dateutilsPaket erforderlich, das über verfügbar ist apt. ( sudo apt install dateutils)

Dieses Skript berücksichtigt auch die aktuelle Verfügbarkeit (aktuelle Sitzung) und ist daher genauer. Sekunden werden nicht gezählt. Die niedrigste gemeldete Einheit ist die Minute.

#!/bin/bash
# Total uptime reported.
temp=$(last reboot --since 2016-01-01 --until 2016-12-31 | grep -o '(.*)' | grep  -v '-' | sed 's/(\([0-9]\{1,\}\)+\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1d\2h\3m/g ;s/(\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1h\2m/g'  )
curr=$( cat /proc/uptime |  perl -ne '/(\d*)/ ; printf "%02d:%02d:%02d\n",int($1/86400),int(($1%86400)/3600),int(($1%3600)/60)'  )
echo "Total run time (days:hours:minutes)"
curr="2015-01-01T"$curr
org="2015-01-01T00:00:00"
new=$(dateutils.dadd $curr $temp )
dateutils.ddiff $org $new -f "%dd %Hh %Mm"
  • Zunächst werden die Betriebszeiten seit dem letzten Neustart aufgelistet und formatiert, um die Informationen zu Tag, Stunden, Minuten und Sekunden zu extrahieren. Dies wird dann in gespeichert temp.
  • Als Referenz-Fälschungsdatum wird org = festgelegt, 2015-01-01zu dem die aktuelle Betriebszeit hinzugefügt wird.
  • Dann werden alle kumulativen Betriebszeiten zur Variablen hinzugefügt new
  • Die Dauer zwischen orgund die Nettoverfügbarkeit newergibt sich aus der Differenz.

Ausgabe:

vayu@helix:$ ./uptime_record.sh
Total run time (days:hours:minutes)
57d 20h 36m

Das folgende Skript gilt für die Verfügbarkeit in genau einem Jahr ab dem Tag, an dem das Skript ausgeführt wird .

#!/bin/bash
# Total uptime reported since exactly 1 year (from the time script is run).
now="$(date +'%Y-%m-%d')" ;
last_y=$(dateutils.dadd $now -1y)
temp=$(last reboot --since "$last_y" --until "$now" | grep -o '(.*)' | grep  -v '-' | sed 's/(\([0-9]\{1,\}\)+\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1d\2h\3m/g ;s/(\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1h\2m/g'  )
curr=$( cat /proc/uptime |  perl -ne '/(\d*)/ ; printf "%02d:%02d:%02d\n",int($1/86400),int(($1%86400)/3600),int(($1%3600)/60)'  )
echo "Total run time in one year (days:hours:minutes)"
curr="1980-01-01T"$curr
org="1980-01-01T00:00:00"
new=$(dateutils.dadd $curr $temp )
dateutils.ddiff $org $new -f "%dd %Hh %Mm"
ankit7540
quelle
1
Irgendwie mag ich Bash-Skripte, aber ich weiß hier, dass elegantere Antworten möglich sind.
Ankit7540
Nach deinem Drehbuch verbringe ich im letzten Jahr 2258 Tage, 01 Stunden, 15 Minuten online.
Daltonfury42
Fehler behoben. Code auf 8 Zeilen komprimiert.
Ankit7540
5

Hier ist eine Python-Implementierung dessen, was ich will, aber ich bin sicher, dass es eine elegante Möglichkeit gibt, dies mit bash zu tun:

import subprocess
output = subprocess.run("last reboot --since 2016-01-01 --until 2016-12-31 | grep -o '(.*)' | grep  -v '-'| sed -e 's/(//g; s/)//g; s/+/:/g'", shell=True, stdout=subprocess.PIPE, universal_newlines=True)
mins_total = 0

for line in output.stdout.split('\n')[:-1]:
    try:
        (hrs, mins) = [int(k) for k in line.split(':')]
        days = 0
    except:
        (days, hrs, mins) = [int(k) for k in line.split(':')]
    mins_total += (days*24 + hrs)*60 + mins

print("Hours: " + str(mins_total/60))
print("Days: " + str(mins_total/60/24))
daltonfury42
quelle
3
"Ich bin sicher, es gibt eine elegante Möglichkeit, dies mit Bash zu tun." IMHO Python ist eine bessere Wahl. Bash ist gut für Dateimanipulationen, nicht für Berechnungen.
Melebius