Как узнать общее время, проведенное на ноутбуке в этом году?


17

Мне интересно узнать общее время, которое я потрачу на работу над ноутбуком в 2016 году.

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

дает мне общее время работы ноутбука в этом формате:

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

Теперь, как мне это сложить?


Можете ли вы сказать мне значение (1 + 06: 41)?
Кашиш

@kashish 1 день, 6 часов, 41 минута
Muru

Дело в том, что wtmpжурналы (что вы видите в выходных данных lastкоманды) настроены на ротацию ежемесячно (в /etc/logrotate.conf), что означает, что после определенного периода времени самый старый журнал удаляется. Другими словами, что бы вы ни пытались сделать last, это не будет точным
Сергей Колодяжный

@Serg Я отключил logrotate для wtmp. Прошло уже больше года с тех пор, как я это сделал, и размер файла в настоящее время составляет 3,7 млн. Поэтому я не вижу причин, по которым его следует поворачивать ежемесячно. ;)
daltonfury42

@ daltonfury42 Если он отключен, он не будет вращаться. Большинство пользователей этого не делают.
Сергей Колодяжный

Ответы:


5

Вот версия 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
        }'

lastПоследний столбец в формате (<days>+hours:minutes), где days+удаляется, если период меньше 1 дня.

Здесь первая awkкоманда выводит последний столбец, интересующую продолжительность, для rebootзаписей.

Для второй awkкоманды:

  1. FSесть [(+:)], то есть скобки или + или : . Таким образом, (h:m)расщепляется на , h, mи (первый и последние поля пустые), и (d+h:m)делятся на , d,h , mи (опять же , первый и последние пустой).
  2. Затем мы берем второе-последнее поле для минут, третье-последнее для часов и четвертое-последнее для дней. Четвертое-последнее поле будет первым, пустым, если дней нет. Итак, мы будем просто добавлять0 в этом случае.
  3. Затем мы увеличиваем часы и дни, если минуты и часы превышают 60 и 24 соответственно. Обратите внимание, что awk выполняет деление с плавающей запятой, поэтомуh и в dнастоящее время может иметь дробные части.
  4. Затем мы печатаем числа как целые числа ( %d), поэтому любая дробная часть игнорируется.

8

Попытка использования bash-скрипта и расширение вашей команды. Я использую, dateutilsчтобы сложить продолжительность времени.

Следовательно, чтобы использовать этот скрипт, нужен dateutilsпакет, доступный через apt. ( sudo apt install dateutils)

Этот сценарий также учитывает текущее время безотказной работы (текущую сессию) и, следовательно, более точный. Секунды не учитываются. Самая низкая заявленная единица - минута.

#!/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"
  • Сначала перечисляется время простоя после последней перезагрузки и форматируется для извлечения дня, часов, минут и второй информации. Это затем сохраняется в temp.
  • Ссылочная фиктивная дата устанавливается с именем org =, 2015-01-01к которой добавляется текущее время безотказной работы.
  • Затем все кумулятивные простои добавляются к переменной new
  • Продолжительность между orgи временем безотказной работы newопределяется разницей.

Выход:

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

Следующий скрипт предназначен для безотказной работы ровно через год со дня запуска скрипта .

#!/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"

1
Почему-то мне нравятся скрипты bash, но я знаю, что здесь возможны более элегантные ответы.
ankit7540 22.12.16

Согласно вашему сценарию, я провожу 2258 дней, 01 часов, 15 минут онлайн в прошлом году.
daltonfury42

Ошибка исправлена. Код сжат до 8 строк.
ankit7540 22.12.16

5

Вот реализация Python того, что я хочу, но я уверен, что есть элегантный способ сделать это с помощью 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))

3
«Я уверен, что есть элегантный способ сделать это с помощью bash». ИМХО Python - лучший выбор. Bash хорош для манипуляций с файлами, а не для расчетов.
Мелебиус
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.