マシン起動時からの経過秒数をhuman-readableな時刻に変換するワンライナー
例えば dmesg(1)
を打つと時刻表示はマシン起動時からの経過秒数になってて((Linuxカーネルのビルド時オプションが CONFIG_PRINTK_TIME=y
になってるのを仮定.こうすると printk
でリング・バッファに出したメッセージにそのような経過秒数が付加される.最近はほとんどそうなってるんじゃないかな.)),注目している事象が起きたのがいつなのか直感的に分かり辛い.そんなときにとりあえずどうするか.例えば,
[1023695.512464] dpkg[32324]: segfault at 10014 ip 080527e8 sp bfdd71f8 error 6 in dpkg[8048000+32000]
この "1023695" をコピペして,
$ date --date @$(($(date --date "`cut -d. -f1 /proc/uptime` seconds ago" +%s) + 1023695 )) 2011年 4月 9日 土曜日 15:18:40 JST
分かりやすくなった.
説明:
- 例えば
date --date '1234 seconds ago' とすると,現在時刻から 1234 秒前の時刻を入力に設定できる
/proc/uptime
からは,空白区切りで「起動時からの経過秒数」と「起動時からの累積idle秒数」が得られる.どちらも小数表示なので,前者の小数点より前だけをcut(1)
で切り出すdate +%s
とすると,出力時刻の書式をEpochからの経過秒数に設定できる- 例えば
date --date @1023695
とすると,Epochからの経過秒数で入力時刻を設定できる(この例では Epoch + 1023695 秒)
発展形として dmesg
のラッパを作ってしまうことも考えられる.^[\d+.\d+]
のパターンを認識して勝手に上記のような変換を施すスクリプトをRubyか何かで書くのだ.まぁでも,当面は手動で十分かな...
と言うか,どっかにもっと簡単な方法は無いのかな?
追記:全部Bashでラッパを作るには,例えば:
$ dmesg|tail -5 [ 12.944753] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready [ 23.648023] eth0: no IPv6 routers present [ 118.304654] EXT4-fs (sda6): re-mounted. Opts: errors=remount-ro,commit=0 [ 118.374839] EXT4-fs (sda7): re-mounted. Opts: commit=0 [ 118.413960] EXT4-fs (sdb2): re-mounted. Opts: commit=0
これが
$ d1=`cut -d. -f1 /proc/uptime`; dmesg|tail -n5|while read l; do l1=${l%%.*}; date --date "$[$d1 - ${l1:1}] seconds ago" +"[%x %X]${l#*]}"; done [2011年08月18日 07時19分51秒] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready [2011年08月18日 07時20分02秒] eth0: no IPv6 routers present [2011年08月18日 07時21分37秒] EXT4-fs (sda6): re-mounted. Opts: errors=remount-ro,commit=0 [2011年08月18日 07時21分37秒] EXT4-fs (sda7): re-mounted. Opts: commit=0 [2011年08月18日 07時21分37秒] EXT4-fs (sdb2): re-mounted. Opts: commit=0
となる.手抜きのため, dmesg(1)
の出力内に date(1)
の書式文字として解釈できる %
○○ があると腐るが... まぁ直したかったら直して.