Jak znaleźć całkowity czas spędzony na moim laptopie w tym roku?

17

Chciałbym poznać całkowity czas pracy na moim laptopie w 2016 roku.

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

daje mi całkowity czas pracy laptopa w tym formacie:

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

Jak teraz to dodać?

daltonfury42
źródło
czy możesz mi powiedzieć znaczenie (1 + 06: 41)?
kashish
@kashish 1 dzień, 6 godzin, 41 minut
mur
Chodzi o to, że wtmpdzienniki (co widać w wynikach lastpolecenia) są ustawione tak, aby obracały się co miesiąc (w /etc/logrotate.conf), co oznacza, że ​​po pewnym czasie najstarszy dziennik zostanie usunięty. Innymi słowy, cokolwiek próbujesz zrobić last, to nie będzie dokładne
Sergiy Kolodyazhnyy,
@Serg Wyłączyłem logrotate dla wtmp. Od tego czasu minął ponad rok, a rozmiar pliku wynosi obecnie 3,7 mln. Więc nie widzę żadnego powodu, dla którego powinien być zmieniany co miesiąc. ;)
daltonfury42
@ daltonfury42 Jeśli jest wyłączone, nie będzie się obracać. Większość użytkowników tego nie robi.
Sergiy Kolodyazhnyy

Odpowiedzi:

5

Oto wersja awk + awk:

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
        }'

lastostatnia kolumna ma format (<days>+hours:minutes), w którym days+jest upuszczany, jeśli okres jest krótszy niż 1 dzień.

Tutaj pierwsze awkpolecenie wyprowadza ostatnią kolumnę, czas trwania zainteresowania, dla rebootwpisów.

Dla drugiego awkpolecenia:

  1. FSto jest [(+:)]nawias lub + lub : . Tak, (h:m)jest podzielony na , h, mi (pierwszy i ostatni pola puste) i (d+h:m)jest podzielony na , d, h, mi (ponownie, pierwszy i ostatni pola puste).
  2. Następnie bierzemy pole przedostatnie na minuty, trzecie na godziny i czwarte na dni. Pole od czwartego do ostatniego będzie pierwszym, pustym polem, jeśli dni nie będą obecne. 0W tym przypadku dodamy po prostu .
  3. Następnie zwiększamy godziny i dni, jeśli minuty i godziny przekraczają odpowiednio 60 i 24. Zauważ, że awk ma zmiennoprzecinkowych podział, więc hi dmoże teraz mieć części ułamkowych.
  4. Następnie wypisujemy liczby jako liczby całkowite ( %d), więc każda część ułamkowa jest ignorowana.
muru
źródło
8

Próbowanie ze skryptem bash i rozszerzenie polecenia. Używam dateutilsdo zsumowania czasu trwania.

Dlatego do korzystania z tego skryptu potrzebny jest dateutilspakiet dostępny za pośrednictwem apt. ( sudo apt install dateutils)

Ten skrypt bierze również pod uwagę bieżący czas pracy (bieżąca sesja), a zatem dokładniejszy. Sekundy nie są liczone. Najniższa zgłoszona jednostka to minuta.

#!/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"
  • Najpierw są wyświetlane czasy przestoju od ostatniego restartu i sformatowane w celu wyodrębnienia dnia, godzin, minut i drugiej informacji. To jest następnie zapisywane w temp.
  • Ustawiono fałszywą datę odniesienia o nazwie org =, 2015-01-01do której dodano bieżący czas działania.
  • Następnie wszystkie skumulowane czasy działania są dodawane do zmiennej new
  • Różnica pomiędzy czasem trwania orga czasem pracy netto new.

Wynik:

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

Poniższy skrypt dotyczy czasu przestoju dokładnie za rok od dnia uruchomienia skryptu .

#!/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
źródło
1
Jakoś lubię skrypty bash, ale wiem tutaj, że możliwe są bardziej eleganckie odpowiedzi.
ankit7540,
Według twojego skryptu spędziłem 2258 dni, 01 godzin, 15 minut online w zeszłym roku.
daltonfury42
Błąd naprawiony. Kod skompresowany do 8 linii.
ankit7540,
5

Oto implementacja Pythona tego, czego chcę, ale jestem pewien, że istnieje elegancki sposób na zrobienie tego za pomocą bash:

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
źródło
3
„Jestem pewien, że istnieje elegancki sposób na zrobienie tego za pomocą bash” IMHO Python jest lepszym wyborem. Bash jest dobry do manipulacji plikami, a nie do obliczeń.
Melebius