Como encontrar o tempo total que gastei no meu laptop neste ano?

17

Estou interessado em saber o tempo total que gasto trabalhando no meu laptop em 2016.

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

fornece o tempo de atividade total do laptop neste formato:

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

Agora, como faço para adicioná-lo?

daltonfury42
fonte
você pode me dizer o significado de (1 + 06: 41)?
Kashish
@kashish 1 dia, 6 horas, 41 minutos
muru
O problema é que os wtmplogs (que é o que você vê na saída do lastcomando) são configurados para girar mensalmente (in /etc/logrotate.conf), o que significa que, após certo período de tempo, o log mais antigo é excluído. Em outras palavras, o que você estiver tentando fazer last, não será preciso #
Sergiy Kolodyazhnyy
@Serg Eu desabilitei o logrotate para wtmp. Faz mais de um ano desde que fiz isso, e o tamanho do arquivo é atualmente de 3,7 milhões. Portanto, não vejo nenhuma razão para que ele seja rotacionado mensalmente. ;)
daltonfury42
@ daltonfury42 Se estiver desativado, não será rotacionado. A maioria dos usuários não faz isso.
Sergiy Kolodyazhnyy

Respostas:

5

Aqui está uma versão 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
        }'

lastA última coluna da coluna está no formato (<days>+hours:minutes), onde days+é eliminada se o período for menor que 1 dia.

Aqui, o primeiro awkcomando gera a última coluna, a duração do interesse, para as rebootentradas.

Para o segundo awkcomando:

  1. FSé [(+:)], ou seja, parênteses ou + ou : . Então, (h:m)é dividida para , h, me (primeiro e último campos vazios), e (d+h:m)é dividida para , d, h, me (novamente, primeiro e último campos vazios).
  2. Depois, pegamos o segundo último campo por minutos, o terceiro último por horas e o quarto último por dias. O quarto e último campo será o primeiro campo vazio se os dias não estiverem presentes. Então, vamos simplesmente adicionar 0neste caso.
  3. Em seguida, aumentamos as horas e os dias se os minutos e as horas estiverem acima de 60 e 24, respectivamente. Observe que o awk faz divisão de ponto flutuante he , portanto, dagora pode ter partes fracionárias.
  4. Em seguida, imprimimos os números como números inteiros ( %d), para que qualquer parte fracionária seja ignorada.
muru
fonte
8

Tentando com o script bash e estendendo seu comando. Eu uso dateutilspara adicionar a duração do tempo.

Portanto, para usar esse script, é necessário o dateutilspacote disponível apt. ( sudo apt install dateutils)

Esse script também leva em consideração o tempo de atividade atual (sessão atual), portanto, mais preciso. Segundos não são contados. A unidade mais baixa relatada é 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"
  • Primeiro, as horas de atividade da última reinicialização são listadas e formatadas para extrair as informações do dia, horas, minutos e segundos. Isso é salvo em temp.
  • É definida uma data de referência falsa chamada org =, 2015-01-01à qual o tempo de atividade atual é adicionado.
  • Em seguida, todos os tempos de atividade cumulativos são adicionados à variável new
  • A duração entre orge o tempo de atividade líquido newé encontrada por diferença.

Resultado:

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

O script a seguir é para o tempo de atividade em exatamente um ano a partir do dia em que o script é executado .

#!/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
fonte
1
De alguma forma, gosto de scripts bash, mas sei aqui que respostas mais elegantes são possíveis.
ankit7540
De acordo com o seu script, passo 2258 dias, 01 horas e 15 minutos online no ano passado.
daltonfury42
Erro corrigido. Código compactado em 8 linhas.
ankit7540
5

Aqui está uma implementação em python do que eu quero, mas tenho certeza de que há uma maneira elegante de fazer isso com o 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
fonte
3
“Tenho certeza de que existe uma maneira elegante de fazer isso com o bash” O IMHO Python é uma escolha melhor. O Bash é bom para manipulações de arquivos, não para cálculos.
Melebius