¿Cómo encontrar el tiempo total que pasé en mi computadora portátil este año?

17

Estoy interesado en saber el tiempo total que paso trabajando en mi computadora portátil en 2016.

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

me da el tiempo de actividad total de la computadora portátil en este formato:

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

Ahora, ¿cómo lo sumo?

daltonfury42
fuente
¿Me puede decir el significado de (1 + 06: 41)?
kashish
@kashish 1 día, 6 horas, 41 minutos
muru
La cuestión es que los wtmpregistros (que es lo que ve en la salida del lastcomando) están configurados para rotar mensualmente (en /etc/logrotate.conf), lo que significa que después de cierto período de tiempo, el registro más antiguo se elimina. En otras palabras, sea lo que sea que intente hacer last, no será exacto
Sergiy Kolodyazhnyy,
@Serg He deshabilitado logrotate para wtmp. Hace más de un año que hice eso, y el tamaño del archivo es actualmente de 3.7M. Así que no veo ninguna razón por la que deba rotarse mensualmente. ;)
daltonfury42
@ daltonfury42 Si está desactivado, no rotará. La mayoría de los usuarios no hacen eso.
Sergiy Kolodyazhnyy

Respuestas:

5

Aquí hay una versión 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
        }'

lastLa última columna está en el formato (<days>+hours:minutes), donde days+se descarta si el período es inferior a 1 día.

Aquí, el primer awkcomando genera la última columna, la duración del interés, para las rebootentradas.

Para el segundo awkcomando:

  1. FSes [(+:)], es decir, paréntesis o + o : . Por lo tanto, (h:m)se divide a , h, my (primero y último campos vacíos), y (d+h:m)se divide a , d, h, my (de nuevo, primero y último campos vacíos).
  2. Luego tomamos el penúltimo campo por minutos, el penúltimo por horas y el penúltimo por días. El último campo será el primer campo vacío si los días no están presentes. Entonces, simplemente agregaremos 0en este caso.
  3. Luego aumentamos las horas y los días si los minutos y las horas están por encima de 60 y 24 respectivamente. Tenga en cuenta que no awk flotante división de punto, así hy dahora puede tener partes fraccionarias.
  4. Luego imprimimos los números como enteros ( %d), por lo que se ignora cualquier parte fraccionaria.
muru
fuente
8

Intentando con bash script y extendiendo tu comando. Yo uso dateutilspara sumar la duración del tiempo.

Por lo tanto, para usar este script, se necesita el dateutilspaquete disponible a través de apt. ( sudo apt install dateutils)

Este script también tiene en cuenta el tiempo de actividad actual (sesión actual), por lo tanto, es más preciso. Los segundos no se cuentan. La unidad más baja reportada es minuto.

#!/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"
  • Primero, el tiempo de actividad desde el último reinicio se enumera y formatea para extraer el día, las horas, los minutos y la segunda información. Esto se guarda en temp.
  • Se establece una fecha falsa de referencia llamada org = 2015-01-01a la cual se agrega el tiempo de actividad actual.
  • Luego, todos los tiempos de actividad acumulados se agregan a la variable new
  • La duración entre orgy el tiempo de actividad neto newse encuentra por diferencia.

Salida:

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

El siguiente script es para el tiempo de actividad en exactamente un año a partir del día en que se ejecuta el script .

#!/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
fuente
1
De alguna manera me gustan los guiones bash, pero sé que aquí son posibles respuestas más elegantes.
ankit7540
Según su guión, pasé 2258 días, 01 horas, 15 minutos en línea el año pasado.
daltonfury42
Error solucionado Código compactado a 8 líneas.
ankit7540
5

Aquí hay una implementación de Python de lo que quiero, pero estoy seguro de que hay una manera elegante de hacerlo con 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
fuente
3
"Estoy seguro de que hay una manera elegante de hacerlo con bash". En mi opinión, Python es una mejor opción. Bash es bueno para manipulaciones de archivos, no para cálculos.
Melebius