Chuyển đổi dấu thời gian dmesg sang định dạng ngày tùy chỉnh


111

Tôi đang cố gắng hiểu dấu thời gian dmesg và cảm thấy khó chuyển đổi dấu thời gian đó để thay đổi nó thành định dạng ngày / ngày tùy chỉnh của java.

Bất kỳ sự giúp đỡ nào cũng được đánh giá cao.

Nhật ký dmesg mẫu:

[14614.647880] airo(eth1): link lost (missed beacons)

Cảm ơn!

Câu trả lời:


179

Hiểu dmesgdấu thời gian khá đơn giản: đó là thời gian tính bằng giây kể từ khi hạt nhân khởi động. Vì vậy, với thời gian khởi động ( uptime), bạn có thể cộng số giây và hiển thị chúng ở bất kỳ định dạng nào bạn thích.

Hoặc tốt hơn, bạn có thể sử dụng -Ttùy chọn dòng lệnh dmesgvà phân tích cú pháp định dạng con người có thể đọc được.

Từ trang người đàn ông :

-T, --ctime
    Print human readable timestamps. The timestamp could be inaccurate!

    The time source used for the logs is not updated after system SUSPEND/RESUME.

10
Lệnh nào chấp nhận -T? Dmesg của tôi không, cả manpage đều không cho biết. (Phiên bản Debian Linux Mint).
gyorgyabraham

1
Của tôi làm ( dmesgtừ util-linux 2.20.1Ubuntu 13.04)

2
Không có sẵn trong redhat và / hoặc oracle linux 5.6, rpm -qf /bin/dmesg => util-linux-2.13-0.56.0.2.el5
michael

7
Tùy chọn này xuất hiện trong util-linux 2.20, theo Ghi chú phát hành: ftp.kernel.org/pub/linux/utils/util-linux/v2.20/…
ks1322

1
@xealits cảm ơn vì đã theo dõi, bạn thật tuyệt :) Về câu hỏi, tôi nghĩ phần hiểu biết là nhỏ và "chuyển đổi nó để thay đổi nó thành ngày java / định dạng ngày tùy chỉnh." là phần cốt lõi, nhưng ý kiến ​​của bạn có thể khác. Chúc một ngày tốt lành;)

32

Với sự trợ giúp của câu trả lời dr , tôi đã viết một cách giải quyết giúp thực hiện chuyển đổi để đưa vào .bashrc của bạn. Nó sẽ không vi phạm bất cứ điều gì nếu bạn không có bất kỳ dấu thời gian nào hoặc dấu thời gian đã chính xác.

dmesg_with_human_timestamps () {
    $(type -P dmesg) "$@" | perl -w -e 'use strict;
        my ($uptime) = do { local @ARGV="/proc/uptime";<>}; ($uptime) = ($uptime =~ /^(\d+)\./);
        foreach my $line (<>) {
            printf( ($line=~/^\[\s*(\d+)\.\d+\](.+)/) ? ( "[%s]%s\n", scalar localtime(time - $uptime + $1), $2 ) : $line )
        }'
}
alias dmesg=dmesg_with_human_timestamps

Ngoài ra, hãy đọc kỹ về logic chuyển đổi dấu thời gian dmesg và cách bật dấu thời gian khi không có dấu thời gian: https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk92677


cải tiến nhỏ: bạn có thể loại bỏ 'tail -1' trong đường dẫn và chỉ để awk ăn các dòng và in từ dòng cuối cùng trong bộ đệm của nó. local dmesg_bin=$(type -a dmesg | awk 'END { print $NF }')
Brian Onn

@Lucas: bạn có thể giải thích bằng cách sử dụng 'type -a dmesg | ...' thay vì $ (dmesg nào) không? Ống 3 tầng có lợi thế gì để đi được đường dẫn đó?
Stabledog

@Stabledog: câu hỏi hay. Để biết giải thích tại sao sử dụng typequá mức which, hãy xem câu hỏi này . Mặc dù vậy, tôi đã chỉnh sửa câu trả lời của mình để tránh dấu ngoặc kép vô dụng.
Lucas Cimon

đoạn mã bash / perl này phù hợp với tôi, tôi có một chiếc máy RHEL5.7 cũ mà tôi phải chăm sóc và dmesg không có tùy chọn để in dấu thời gian theo thời gian của con người.
Paul M

17

Đối với các hệ thống không có "dmesg -T" chẳng hạn như RHEL / CentOS 6, tôi thích chức năng "dmesg_with_human_timestamps" được cung cấp bởi lucas-cimon trước đó. Tuy nhiên, nó có một chút rắc rối với một số hộp của chúng tôi có thời gian hoạt động lớn. Hóa ra rằng dấu thời gian của hạt nhân trong dmesg được lấy từ một giá trị thời gian hoạt động được giữ bởi các CPU riêng lẻ. Theo thời gian, điều này không đồng bộ với đồng hồ thời gian thực. Do đó, chuyển đổi chính xác nhất cho các mục dmesg gần đây sẽ dựa trên đồng hồ CPU thay vì / proc / uptime. Ví dụ: trên một hộp CentOS 6.6 cụ thể ở đây:

# grep "\.clock" /proc/sched_debug  | head -1
  .clock                         : 32103895072.444568
# uptime
 15:54:05 up 371 days, 19:09,  4 users,  load average: 3.41, 3.62, 3.57
# cat /proc/uptime
32123362.57 638648955.00

Tính đến thời gian hoạt động của CPU tính bằng mili giây, có một khoảng thời gian bù đắp là gần 5 giờ rưỡi ở đây. Vì vậy, tôi đã sửa đổi tập lệnh và chuyển đổi nó thành bash gốc trong quá trình này:

dmesg_with_human_timestamps () {
    FORMAT="%a %b %d %H:%M:%S %Y"

    now=$(date +%s)
    cputime_line=$(grep -m1 "\.clock" /proc/sched_debug)

    if [[ $cputime_line =~ [^0-9]*([0-9]*).* ]]; then
        cputime=$((BASH_REMATCH[1] / 1000))
    fi

    dmesg | while IFS= read -r line; do
        if [[ $line =~ ^\[\ *([0-9]+)\.[0-9]+\]\ (.*) ]]; then
            stamp=$((now-cputime+BASH_REMATCH[1]))
            echo "[$(date +"${FORMAT}" --date=@${stamp})] ${BASH_REMATCH[2]}"
        else
            echo "$line"
        fi
    done
}

alias dmesgt=dmesg_with_human_timestamps

Hàm không hoạt động trong zsh. Phải làm điều đó một cách thích hợp. Điều đó nói rằng, trên một hộp có 221 ngày thời gian hoạt động, giải pháp này có dấu thời gian xuống đến phút thực tế. Các giải pháp khác cho thấy nguyên nhân gốc rễ xảy ra sớm hơn 2 giờ trong ngày. Cảm ơn, Allen. Bạn đã cứu buổi chiều của tôi.
Trenton

Máy RHEL5.x dường như không có / proc / Sched_debug :-(
Paul M

14

Vì vậy, KevZero đã yêu cầu một giải pháp ít khó khăn hơn, vì vậy tôi đã đưa ra những điều sau:

sed -r 's#^\[([0-9]+\.[0-9]+)\](.*)#echo -n "[";echo -n $(date --date="@$(echo "$(grep btime /proc/stat|cut -d " " -f 2)+\1" | bc)" +"%c");echo -n "]";echo -n "\2"#e'

Đây là một ví dụ:

$ dmesg|tail | sed -r 's#^\[([0-9]+\.[0-9]+)\](.*)#echo -n "[";echo -n $(date --date="@$(echo "$(grep btime /proc/stat|cut -d " " -f 2)+\1" | bc)" +"%c");echo -n "]";echo -n "\2"#e'
[2015-12-09T04:29:20 COT] cfg80211:   (57240000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 0 mBm), (N/A)
[2015-12-09T04:29:23 COT] wlp3s0: authenticate with dc:9f:db:92:d3:07
[2015-12-09T04:29:23 COT] wlp3s0: send auth to dc:9f:db:92:d3:07 (try 1/3)
[2015-12-09T04:29:23 COT] wlp3s0: authenticated
[2015-12-09T04:29:23 COT] wlp3s0: associate with dc:9f:db:92:d3:07 (try 1/3)
[2015-12-09T04:29:23 COT] wlp3s0: RX AssocResp from dc:9f:db:92:d3:07 (capab=0x431 status=0 aid=6)
[2015-12-09T04:29:23 COT] wlp3s0: associated
[2015-12-09T04:29:56 COT] thinkpad_acpi: EC reports that Thermal Table has changed
[2015-12-09T04:29:59 COT] i915 0000:00:02.0: BAR 6: [??? 0x00000000 flags 0x2] has bogus alignment
[2015-12-09T05:00:52 COT] thinkpad_acpi: EC reports that Thermal Table has changed

Nếu bạn muốn nó hoạt động tốt hơn một chút, hãy đặt dấu thời gian từ proc vào một biến thay thế :)


4

Trong các phiên bản gần đây của dmesg, bạn chỉ có thể gọi dmesg -T.


3
Câu trả lời tương tự đã được RC đưa ra trước bạn hai năm.
josch

4

Nếu bạn không có -Ttùy chọn, dmesgchẳng hạn như trên Andoid, bạn có thể sử dụng busyboxphiên bản. Phần sau cũng giải quyết một số vấn đề khác:

  1. Các [0.0000]định dạng được đi trước bởi một cái gì đó trông giống như thông tin màu không đúng chỗ, tiền tố thích <6>.
  2. Tạo số nguyên từ phao.

Nó được lấy cảm hứng từ bài đăng trên blog này .

#!/bin/sh                                                                                                               
# Translate dmesg timestamps to human readable format                                                                   

# uptime in seconds                                                                                                     
uptime=$(cut -d " " -f 1 /proc/uptime)                                                                                  

# remove fraction                                                                                                       
uptime=$(echo $uptime | cut -d "." -f1)                                                                                 

# run only if timestamps are enabled                                                                                    
if [ "Y" = "$(cat /sys/module/printk/parameters/time)" ]; then                                                          
  dmesg | sed "s/[^\[]*\[/\[/" | sed "s/^\[[ ]*\?\([0-9.]*\)\] \(.*\)/\\1 \\2/" | while read timestamp message; do      
    timestamp=$(echo $timestamp | cut -d "." -f1)                                                                       
    ts1=$(( $(busybox date +%s) - $uptime + $timestamp ))                                                               
    ts2=$(busybox date -d "@${ts1}")                                                                                    
    printf "[%s] %s\n" "$ts2" "$message"                                                                                
  done                                                                                                                  
else                                                                                                                    
  echo "Timestamps are disabled (/sys/module/printk/parameters/time)"                                                   
fi                                                                                                                      

Tuy nhiên, lưu ý rằng việc thực hiện này diễn ra khá chậm.


3

bạn sẽ cần tham chiếu "btime" trong / proc / stat, là thời gian của kỷ nguyên Unix khi hệ thống được khởi động gần đây nhất. Sau đó, bạn có thể dựa trên thời gian khởi động hệ thống đó và sau đó thêm vào số giây đã trôi qua được cho trong dmesg để tính dấu thời gian cho mỗi sự kiện.


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.