Làm thế nào để tìm tổng thời gian tôi dành cho máy tính xách tay của mình trong năm nay?


17

Tôi quan tâm đến việc biết tổng thời gian tôi làm việc trên máy tính xách tay của mình vào năm 2016.

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

cung cấp cho tôi tổng thời gian hoạt động của máy tính xách tay ở định dạng này:

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

Bây giờ làm thế nào để tôi thêm nó lên?


bạn có thể cho tôi biết ý nghĩa của (1 + 06: 41) không?
kashish

@kashish 1 ngày, 6 giờ, 41 phút
muru

Vấn đề là wtmpcác bản ghi (là những gì bạn thấy trong đầu ra của lastlệnh) được đặt thành xoay vòng hàng tháng (in /etc/logrotate.conf), nghĩa là sau khoảng thời gian nhất định, nhật ký cũ nhất sẽ bị xóa. Nói cách khác, bất cứ điều gì bạn đang cố gắng thực hiện last, điều đó sẽ không chính xác
Sergiy Kolodyazhnyy

@Serg Tôi đã vô hiệu hóa logrotate cho wtmp. Đã hơn một năm kể từ khi tôi làm điều đó và kích thước tệp hiện là 3,7 triệu. Vì vậy, tôi không thấy bất kỳ lý do tại sao nó nên được luân chuyển hàng tháng. ;)
daltonfury42

@ daltonfury42 Nếu nó bị vô hiệu hóa, nó sẽ không xoay. Hầu hết người dùng không làm điều đó.
Sergiy Kolodyazhnyy

Câu trả lời:


5

Đây là phiên bả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
        }'

lastCột cuối cùng có định dạng (<days>+hours:minutes), nơi days+bị bỏ nếu thời gian ít hơn 1 ngày.

Ở đây, awklệnh đầu tiên xuất ra cột cuối cùng, thời gian quan tâm, cho rebootcác mục.

Đối với awklệnh thứ hai :

  1. FS[(+:)], ví dụ, dấu ngoặc đơn hoặc + hoặc : . Vì vậy, (h:m)là chia để , h, m(đầu tiên và các lĩnh vực cuối cùng trống), và (d+h:m)được tách ra để , d, h, m(một lần nữa, lần đầu tiên và các lĩnh vực cuối cùng trống rỗng).
  2. Sau đó, chúng tôi lấy trường cuối cùng thứ hai trong vài phút, thứ ba cuối cùng trong nhiều giờ và thứ tư cuối cùng trong nhiều ngày. Trường thứ tư cuối cùng sẽ là trường đầu tiên, trống, nếu không có ngày. Vì vậy, chúng tôi sẽ chỉ cần thêm 0vào trong trường hợp này.
  3. Sau đó, chúng tôi tăng số giờ và ngày bằng cách nếu phút và giờ tương ứng trên 60 và 24. Lưu ý rằng awk không phân chia điểm nổi, vì vậy hdbây giờ có thể có các phần phân số.
  4. Sau đó, chúng tôi in các số dưới dạng số nguyên ( %d), vì vậy bất kỳ phần phân số nào cũng bị bỏ qua.

8

Cố gắng với bash script và mở rộng lệnh của bạn. Tôi sử dụng dateutilsđể thêm thời gian.

Do đó để sử dụng tập lệnh này, người ta cần dateutilsgói có sẵn thông qua apt. ( sudo apt install dateutils)

Kịch bản này cũng tính đến thời gian hoạt động hiện tại (phiên hiện tại), do đó chính xác hơn. Giây không được tính. Đơn vị thấp nhất báo cáo là phút.

#!/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"
  • Đầu tiên, các mức tăng từ lần khởi động lại cuối cùng được liệt kê và định dạng để trích xuất thông tin ngày, giờ, phút và thông tin thứ hai. Điều này sau đó được lưu vào temp.
  • Ngày giả mạo tham chiếu được đặt tên là org = 2015-01-01mà thời gian hoạt động hiện tại được thêm vào.
  • Sau đó, tất cả các mức tăng tích lũy được thêm vào biến new
  • Thời lượng giữa orgvà thời gian hoạt động ròng newđược tìm thấy bởi sự khác biệt.

Đầu ra:

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

Kịch bản sau đây dành cho thời gian hoạt động trong đúng một năm kể từ ngày tập lệnh được chạy .

#!/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
Bằng cách nào đó tôi thích kịch bản bash, nhưng tôi biết ở đây có thể có câu trả lời thanh lịch hơn.
ankit7540

Theo kịch bản của bạn, tôi dành 2258 ngày, 01 giờ, 15 phút trực tuyến vào năm ngoái.
daltonfury42

Đã sửa lỗi. Mã được nén thành 8 dòng.
ankit7540

5

Đây là một triển khai python của những gì tôi muốn, nhưng tôi chắc chắn có một cách thanh lịch để làm điều đó với 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
Tôi chắc chắn có một cách thanh lịch để làm điều đó với bash. IMHO Python là một lựa chọn tốt hơn. Bash là tốt cho các thao tác tập tin, không phải cho tính toán.
Melebius
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.