dmesg 타임 스탬프를 사용자 지정 날짜 형식으로 변환


111

dmesg 타임 스탬프를 이해하려고 노력하고 있으며 Java 날짜 / 사용자 지정 날짜 형식으로 변경하기 위해 변환하기가 어렵습니다.

어떤 도움이라도 대단히 감사합니다.

샘플 dmesg 로그 :

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

감사!

답변:


179

dmesg타임 스탬프를 이해하는 것은 매우 간단합니다. 커널이 시작된 이후의 시간입니다. 따라서 시작 시간 ( uptime)이 있으면 초를 더하여 원하는 형식으로 표시 할 수 있습니다.

또는 -T명령 줄 옵션을 사용 dmesg하여 사람이 읽을 수있는 형식을 구문 분석 할 수 있습니다 .

로부터 man 페이지 :

-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는 그렇지 않으며 맨 페이지에서도 알려줍니다. (리눅스 민트 데비안 에디션).
gyorgyabraham

1
광산 (하지 dmesg에서 util-linux 2.20.113.04 우분투 아래)

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 : $ (which dmesg) 대신 'type -a dmesg | ...'를 사용하여 설명 할 수 있습니까? 그 경로를 얻기 위해 3 단계 파이프가 이점이 있습니까?
Stabledog

@Stabledog : 좋은 질문입니다. typeover를 사용하는 이유에 대한 설명 which이 질문을 참조하십시오 . 쓸모없는 트리플 파이프를 피하기 위해 내 대답을 편집했습니다.
Lucas Cimon 2014 년

이 bash / perl 스 니펫은 저에게 효과적이었습니다. 예전 RHEL5.7 머신을 관리해야하는데 dmesg에는 인간 시간으로 타임 스탬프를 인쇄하는 옵션이 없습니다.
Paul M

17

RHEL / CentOS 6과 같이 "dmesg -T"가없는 시스템의 경우 이전 에 lucas-cimon이 제공 한 "dmesg_with_human_timestamps"기능이 마음에 들었습니다 . 그러나 가동 시간이 큰 일부 상자에는 약간의 문제가 있습니다. dmesg의 커널 타임 스탬프는 개별 CPU에서 유지하는 가동 시간 값에서 파생 된 것으로 나타났습니다. 시간이 지남에 따라 실시간 시계와 동기화되지 않습니다. 결과적으로 최근 dmesg 항목에 대한 가장 정확한 변환은 / proc / uptime이 아닌 CPU 클럭을 기반으로합니다. 예를 들어, 특정 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 시간 반의 오프셋이 있습니다. 그래서 스크립트를 수정하고 프로세스에서 네이티브 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에서 기능이 작동하지 않았습니다. 적절한 bash에서 그것을해야했습니다. 즉, 221 일의 가동 시간이있는 박스에서이 솔루션은 실제 분까지 타임 스탬프를 가졌습니다. 다른 솔루션은 하루에 2 시간 이상 일찍 발생하는 근본 원인 이벤트를 보여주었습니다. 고마워, 앨런. 당신은 내 오후를 구했습니다.
Trenton

RHEL5.x 기계 / proc 디렉토리 / sched_debug :-(없는 것 같습니다
폴 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

최신 버전의 dmesg에서는 dmesg -T.


3
RC는 당신보다 2 년 전에 이미 같은 대답을했습니다.
josch

4

예를 들어 Andoid에 대한 -T옵션 이없는 경우 버전을 dmesg사용할 수 있습니다 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 epoch 시간입니다. 그런 다음 해당 시스템 부팅 시간을 기반으로 dmesg에 지정된 경과 시간 (초)을 추가하여 각 이벤트의 타임 스탬프를 계산할 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.