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にはありません。どちらのマンページにも記載されていません。(Linux Mint Debianエディション)。
gyorgyabraham 2013年

1
鉱山は(Ubuntu 13.04 dmesgからutil-linux 2.20.1

2
redhatやoracle linux 5.6では使用できませんrpm -qf /bin/dmesg => util-linux-2.13-0.56.0.2.el5
マイケル

7
このオプションは、に登場しutil-linux 2.20、リリースノートによると、:ftp.kernel.org/pub/linux/utils/util-linux/v2.20/...
ks1322

1
@xealitsフォローありがとうございます。よろしくお願いします:)質問については、理解の部分はマイナーであり、「変換してJava日付/カスタム日付形式に変更する」と思います。コア部分でしたが、あなたの意見は異なる場合があります。よい一日をお過ごしください;)

32

dr answer の助けを借りて、.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 2013

@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時間前に発生したことが示されました。ありがとう、アレン。あなたは私の午後を救った。
2016

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

dmesgの最近のバージョンでは、を呼び出すだけdmesg -Tです。


3
同じ答えは、あなたの2年前にRCによってすでに与えられました。
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エポック時間です。次に、そのシステムの起動時間に基づいて、dmesgで指定された経過秒数を加算して、各イベントのタイムスタンプを計算します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.