将dmesg时间戳转换为自定义日期格式


111

我试图理解dmesg时间戳,发现很难将其转换为将其更改为Java日期/自定义日期格式。

任何帮助深表感谢。

样本dmesg日志:

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

谢谢!

Answers:


179

了解dmesg时间戳非常简单:自内核启动以来,以秒为单位的时间。因此,在有启动时间(uptime)的情况下,您可以将秒数相加并以您喜欢的格式显示它们。

或者更好的是,您可以使用的-T命令行选项dmesg并解析人类可读的格式。

手册页

-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
什么命令接受-T?我的dmesg没有,也没有manpage告诉它。(Linux Mint Debian版)。
gyorgyabraham 2013年

1
我的根本(dmesgutil-linux 2.20.113.04 Ubuntu的下)

2
在Redhat和/或oracle linux 5.6中不可用, rpm -qf /bin/dmesg => util-linux-2.13-0.56.0.2.el5
michael

7
此选项出现在util-linux 2.20,根据发行说明:ftp.kernel.org/pub/linux/utils/util-linux/v2.20/...
ks1322

1
@xealits感谢您的跟进,对您很高兴:)关于这个问题,我认为理解部分很小,并且“将其转换为Java日期/自定义日期格式”。是核心部分,但您的看法可能有所不同。祝您有美好的一天;)

32

dr博士的帮助下,我编写了一种解决方法,将转换结果放入您的.bashrc中。如果您没有任何时间戳或已经正确的时间戳,它不会破坏任何内容。

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

另外,还可以很好地阅读dmesg时间戳转换逻辑以及在没有时间戳时如何启用时间戳:https//supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails =&solutionid = sk92677


较小的改进:您可以删除管道中的“ tail -1”,然后让awk吃掉行并从其缓冲区的最后一行打印。 local dmesg_bin=$(type -a dmesg | awk 'END { print $NF }')
Brian Onn

@Lucas:您能解释使用'type -a dmesg | ...'而不是$(哪个dmesg)吗?3级管道获得该路径是否有优势?
稳定狗2013年

@Stabledog:好问题。有关为何使用typeover 的解释which,请参见此问题。我编辑了答案,以免使用无用的三重管道。
卢卡斯·西蒙

这个bash / perl代码段对我有用,我有一台旧的RHEL5.7机器我必须照顾,而dmesg无法选择打印人类时间的时间戳。
Paul M

17

对于没有“ dmesg -T”的系统(例如RHEL / CentOS 6),我喜欢lucas-cimon先前提供的“ dmesg_with_human_timestamps”功能。但是,某些正常运行时间较长的机器有些麻烦。事实证明,dmesg中的内核时间戳是由各个CPU保持的正常运行时间值得出的。随着时间的流逝,它与实时时钟不同步。结果,最近dmesg条目的最准确转换将基于CPU时钟而不是/ proc / uptime。例如,在此处的特定CentOS 6.6框上:

# 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

考虑到CPU的正常运行时间(以毫秒为单位),这里的偏移量接近5 1/2小时。因此,我修改了脚本并将其转换为本地bash:

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

功能在zsh中不起作用。不得不适当地做它。就是说,在具有221天正常运行时间的机器上,此解决方案的时间戳记可降至实际分钟。其他解决方案显示根本原因事件发生在一天中的早2个小时以上。谢谢,艾伦。你救了我的下午。
特伦顿

RHEL5.x机器似乎没有/ proc / sched_debug :-(
Paul M

14

因此,KevZero要求采用一种不太复杂的解决方案,因此我提出了以下建议:

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'

这是一个例子:

$ 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

如果您希望它的性能更好一些,请将proc的时间戳记改为变量:)



4

如果你不具备-T的选项dmesg,例如在Andoid,你可以使用busybox的版本。以下内容还解决了其他一些问题:

  1. [0.0000]格式是由一些看似错位的颜色信息,前缀喜欢前面<6>
  2. 从浮点数中获取整数。

它受此博客文章的启发。

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

但是请注意,此实现非常慢。


3

您将需要在/ proc / stat中引用“ btime”,这是最新启动系统时的Unix时期。然后,您可以基于该系统启动时间,然后加上dmesg中给出的经过的秒数来计算每个事件的时间戳。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.