After the update to Ubuntu 11.10 my wireless goes up and down, and so i’m trying to debug this problem looking into dmesg
.
But this brought me to another small issue, dmesg
prints timestamps in the form of seconds.nanoseconds since the system booted. And no, there seems to be no -h option to make it human readable. so you should check your boot time and make some calculations to see where the events logged are happened.
This don’t seem so useful !
Let’s see how to have these information in a better format.
First a really short introduction to dmesg
, from the man page:
dmesg is used to examine or control the kernel ring buffer.
In short, giving the command dmesg
from a terminal you can see the boot message or any message regarding the kernel while your system is running. And now back on the logs.
Debian and Ubuntu
While I was looking around for a solution i’ve discovered that for these distributions there is an easy way to solve the problem, instead of using the command dmesg
just check the file /var/log/kern.log
There you’ll see entry like mine, with the date nicely formatted:
Nov 13 18:37:19 xubuntu-home kernel: [14850.508867] airo(eth1): link lost (missed beacons) Nov 13 18:38:29 xubuntu-home kernel: [14920.467041] airo(eth1): link lost (missed beacons) Nov 13 18:38:44 xubuntu-home kernel: [14935.605833] ADDRCONF(NETDEV_UP): eth0: link is not ready Nov 13 18:38:53 xubuntu-home kernel: [14943.868439] ADDRCONF(NETDEV_UP): eth0: link is not ready Nov 13 18:39:03 xubuntu-home kernel: [14954.592045] eth1: no IPv6 routers present Nov 13 18:39:08 xubuntu-home kernel: [14958.742806] type=1400 audit(1321205948.113:29): apparmor="DENIED" operation="open" parent=13015 profile="/sbin/dhclient" name="/var/lib/wicd/dhclient.conf" pid=13067 comm="dhclient" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 Nov 13 19:22:46 xubuntu-home kernel: [17577.082369] airo(eth1): link lost (missed beacons) |
So, problem solved on these distributions.
Fedora, CentOS and all the others
Ok, so your distribution don’t use /var/log/kern.log and so your dmesg show lines like these:
[14614.647880] airo(eth1): link lost (missed beacons) [14850.508867] airo(eth1): link lost (missed beacons) [14920.467041] airo(eth1): link lost (missed beacons) [14935.605833] ADDRCONF(NETDEV_UP): eth0: link is not ready [14943.868439] ADDRCONF(NETDEV_UP): eth0: link is not ready [14954.592045] eth1: no IPv6 routers present [14958.742806] type=1400 audit(1321205948.113:29): apparmor="DENIED" operation="open" parent=13015 profile="/sbin/dhclient" name="/var/lib/wicd/dhclient.conf" pid=13067 comm="dhclient" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 [17577.082369] airo(eth1): link lost (missed beacons) |
I’ve found 2 solutions to parse the dmesg output and have it human readable one in Perl and one in Python.
This is the solution in perl:
#!/usr/bin/perl use strict; use warnings; my @dmesg_new = (); my $dmesg = "/bin/dmesg"; my @dmesg_old = `$dmesg`; my $now = time(); my $uptime = `cat /proc/uptime | cut -d"." -f1`; my $t_now = $now - $uptime; sub format_time { my @time = localtime $_[0]; $time[4]+=1; # Adjust Month $time[5]+=1900; # Adjust Year return sprintf '%4i-%02i-%02i %02i:%02i:%02i', @time[reverse 0..5]; } foreach my $line ( @dmesg_old ) { chomp( $line ); if( $line =~ m/\[\s*(\d+)\.(\d+)\](.*)/i ) { # now - uptime + sekunden my $t_time = format_time( $t_now + $1 ); push( @dmesg_new , "[$t_time] $3" ); } } print join( "\n", @dmesg_new ); print "\n"; |
Just copy and paste these lines in a file, make it executable and run it, you’ll have the dmesg
output but with an human readable time format:
[2011-11-13 16:57:10] airo(eth1): link lost (missed beacons) [2011-11-13 16:57:34] ADDRCONF(NETDEV_UP): eth0: link is not ready [2011-11-13 16:57:50] eth1: no IPv6 routers present [2011-11-13 17:01:22] ADDRCONF(NETDEV_UP): eth0: link is not ready [2011-11-13 17:01:33] eth1: no IPv6 routers present [2011-11-13 17:02:04] ADDRCONF(NETDEV_UP): eth0: link is not ready [2011-11-13 17:04:47] ADDRCONF(NETDEV_UP): eth0: link is not ready [2011-11-13 17:04:54] type=1400 audit(1321200294.812:28): apparmor="DENIED" operation="open" parent=9097 profile="/sbin/dhclient" name="/var/lib/wicd/dhclient.conf" pid=9139 comm="dhclient" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 [2011-11-13 17:04:58] eth1: no IPv6 routers present [2011-11-13 17:08:16] airo(eth1): link lost (missed beacons) |
And if you prefer python this is a solution for this language:
#!/usr/bin/env python # coding=utf8 # Copyright (C) 2010 Saúl ibarra Corretgé <[email protected]> # """ pydmesg: dmesg with human-readable timestamps """ from __future__ import with_statement import re import subprocess import sys from datetime import datetime, timedelta _datetime_format = "%Y-%m-%d %H:%M:%S" _dmesg_line_regex = re.compile("^\[(?P<time>\d+\.\d+)\](?P<line>.*)$") def exec_process(cmdline, silent, input=None, **kwargs): """Execute a subprocess and returns the returncode, stdout buffer and stderr buffer. Optionally prints stdout and stderr while running.""" try: sub = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) stdout, stderr = sub.communicate(input=input) returncode = sub.returncode if not silent: sys.stdout.write(stdout) sys.stderr.write(stderr) except OSError,e: if e.errno == 2: raise RuntimeError('"%s" is not present on this system' % cmdline[0]) else: raise if returncode != 0: raise RuntimeError('Got return value %d while executing "%s", stderr output was:\n%s' % (returncode, " ".join(cmdline), stderr.rstrip("\n"))) return stdout def human_dmesg(): now = datetime.now() uptime_diff = None try: with open('/proc/uptime') as f: uptime_diff = f.read().strip().split()[0] except IndexError: return else: try: uptime = now - timedelta(seconds=int(uptime_diff.split('.')[0]), microseconds=int(uptime_diff.split('.')[1])) except IndexError: return dmesg_data = exec_process(['dmesg'], True) for line in dmesg_data.split('\n'): if not line: continue match = _dmesg_line_regex.match(line) if match: try: seconds = int(match.groupdict().get('time', '').split('.')[0]) nanoseconds = int(match.groupdict().get('time', '').split('.')[1]) microseconds = int(round(nanoseconds * 0.001)) line = match.groupdict().get('line', '') t = uptime + timedelta(seconds=seconds, microseconds=microseconds) except IndexError: pass else: print "[%s]%s" % (t.strftime(_datetime_format), line) if __name__ == '__main__': human_dmesg() |
Copy and paste or download the code from here.
Run the script and once again you’ll get the result that we want:
[2011-11-13 18:37:19] airo(eth1): link lost (missed beacons) [2011-11-13 18:38:29] airo(eth1): link lost (missed beacons) [2011-11-13 18:38:44] ADDRCONF(NETDEV_UP): eth0: link is not ready [2011-11-13 18:38:52] ADDRCONF(NETDEV_UP): eth0: link is not ready [2011-11-13 18:39:03] eth1: no IPv6 routers present [2011-11-13 18:39:07] type=1400 audit(1321205948.113:29): apparmor="DENIED" operation="open" parent=13015 profile="/sbin/dhclient" name="/var/lib/wicd/dhclient.conf" pid=13067 comm="dhclient" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 [2011-11-13 19:22:46] airo(eth1): link lost (missed beacons) |
Conclusions
It seem my problem is related to apparmor and some configuration missing for wicd, so at the moment i’ve add in /etc/apparmor.d/sbin.dhclient an entry:
# wicd /var/lib/wicd/* r, |
And restarted apparmor, let’s see if this works out.
Popular Posts:
- None Found
dmesg -T works for me..
+1
But not for me.
Older versions of dmesg do not have this option. To upgrade dmesg, you need to upgrade the “util-linux” package (Debian based distros). After updating your apt cache, run “sudo apt-get install util-linux”. Dmesg options become:
$ dmesg --help
Usage:
dmesg [options]
Options:
-C, --clear clear the kernel ring buffer
-c, --read-clear read and clear all messages
-D, --console-off disable printing messages to console
-d, --show-delta show time delta between printed messages
-E, --console-on enable printing messages to console
-f, --facility restrict output to defined facilities
-h, --help display this help and exit
-k, --kernel display kernel messages
-l, --level restrict output to defined levels
-n, --console-level set level of messages printed to console
-r, --raw print the raw message buffer
-s, --buffer-size buffer size to query the kernel ring buffer
-T, --ctime show human readable timestamp (could be
inaccurate if you have used SUSPEND/RESUME)
-t, --notime don't print messages timestamp
-u, --userspace display userspace messages
-V, --version output version information and exit
-x, --decode decode facility and level to readable string
Supported log facilities:
kern - kernel messages
user - random user-level messages
mail - mail system
daemon - system daemons
auth - security/authorization messages
syslog - messages generated internally by syslogd
lpr - line printer subsystem
news - network news subsystem
Supported log levels (priorities):
emerg - system is unusable
alert - action must be taken immediately
crit - critical conditions
err - error conditions
warn - warning conditions
notice - normal but significant condition
info - informational
debug - debug-level messages
Not for me, which version/OS are you using ?
On Ubuntu 12.10 (utili-linux v2.20.1-5.1ubuntu2), it works.
Does not on Debian Sqeeze (util-linux, v2.17.2-9) and CentOS 5.8 (util-linux, v2.13-0.59.el5_8) at least.
Thanks Jerome.
alias dmsg_human = dmesg|perl -ne ‘BEGIN{$a= time()- qx!cat /proc/uptime!};s/\[(\d+)\.\d+\]/localtime($1 + $a)/e; print $_;’
Great solution in 1 line.
Thanks Holger
Not working for me on centos 6.3, perl v5.10.1.
getting dmesg logs without time stamp
Sorry for wrong escaping 😉
alias dmsg_human=’dmesg|perl -ne “BEGIN{\$a= time()- qx!cat /proc/uptime!};s/\[(\d+)\.\d+\]/localtime(\$1 + \$a)/e; print ;”‘
*grrr* even one more copy glitch
alias dmsg_human=”dmesg|perl -ne \”BEGIN{\\\$a= time()- qx{cat /proc/uptime}};s/\[(\d+)\.\d+\]/localtime(\\\$1 + \\\$a)/e; print \\\$_;\””
this should work at least.
Perhaps someone can drop the wrong quouted ones.
Explanation for perl-dummies 😉
# use program code from argument line and make an implicit loop to read in stdin.
perl -ne ‘
# the BEGIN block is executed only once and directly after perl startup.
BEGIN{
# calculate the timestamp of systems startup
$a= time()- qx{cat /proc/uptime}
};
# now for every line
# substitute the integer part of dmsg timestamp with a human readable value
s/\[(\d+)\.\d+\]/localtime($1 + $a)/e;
# and print it out
print;
‘
that’s it
its missing to ignore the blanks in front of lower numbers..
alias tmesg=’dmesg|perl -ne “BEGIN{\$a= time()- qx!cat /proc/uptime!};s/\[\s*(\d+)\.\d+\]/localtime(\$1 + \$a)/e; print \$_;”‘
Because you want to keep the arguments you passed, like dmesg -s 65535, in the perl program you just to adapt this line
my $dmesg = “/bin/dmesg @ARGV”;
(By the way, there is a not so user-friendly error about the captcha because i waited too long between the page load and the comment posting.)
There is an error in the python program, there is < and > instead of .
Plus, i would say that both of the program (perl and python) don’t display an accurate time, i have a ten minute delay here.
Great post.
dmesg -T works for me two.
I suggest you update the post and add a note to the first line about this.
Also in bash version:
base=$(cat /proc/uptime | cut -d ‘.’ -f1); seconds=`date +%s`; dmesg | sed ‘s/^\[\(.*\)\..*\]\(.*\)$/\1\n\2/’ | while read first; do read second; first=`date +”%d/%m/%Y %H:%M:%S” –date=”@$(($seconds – $base + $first))”`; echo “[$first] $second”; done
Your bash one-liner looks quite handy. Unfortunately, I am getting these errors:
-bash: -date=@1362748064: command not found
Do you happen to know how I can create the Unicode 2013 character before “date” in the segment (…)–date=”@(…), or replace it with something else?
I think some characters where translated by the comment system. I hope this works: http://pastebin.com/rWRc8BvQ
Yes that works fine, thank you!
However, the one-liner does not work sometimes. For example:
original output from dmesg:
[ 10.097099] e1000 0000:00:03.0: PCI INT A -> Link[LNKC] -> GSI 11 (level, high) -> IRQ 11
filtered output:
-bash: 1363079793 – 73723 + 10.097099] e1000 0000:00:03: syntax error: invalid arithmetic operator (error token is “.097099] e1000 0000:00:03”)
[] -> GSI 11 (level, high) -> IRQ 11
dmesg –help
-T, –ctime show human readable timestamp (could be
inaccurate if you have used SUSPEND/RESUME)
dmesg: invalid option — ‘T’
Usage: dmesg [-c] [-n level] [-r] [-s bufsize]
OS=SLES11.2 (kernel 3.0.13-0.27-pae)
Thanks for the post and the examples. This put me on track to write a quick executable in PHP that you can run as a command:
#!/usr/bin/php
<?php
$cmd = '/bin/dmesg';
$now = time();
$uptime = shell_exec('/bin/cat /proc/uptime | cut -d\' \' -f1');
$boot = $now – $uptime;
print "BOOT TIME: ".date("l, F jS, Y g:i a", $boot)."\n\n";
foreach ( explode("\n",shell_exec($cmd)) as $l )
{
print preg_replace_callback(
':\[([\s\d\.]+)\]:',
function ( $m ) {
global $boot;
return '['. date("D M j Y g:ia", $boot + $m[1]) .']';
},
$l,
1) .
"\n";
}
Hi , i tried to run the perl script but got some errors
perl dmesg.pl
/var/log/dmesg: line 1: syntax error near unexpected token `(‘
/var/log/dmesg: line 1: `Linux version 2.6.32-cdstv.3.5.0.b215 (cdsbuild@cds-build3) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)) #1 SMP Mon Mar 31 14:20:42 PDT 2014’
When it is taking dmesg 1st line itself it is throwing some error. Could you please help me to solve this issue.
thanks, its work
#!/usr/bin/env ruby
#
require 'time'
$now=Time.new.to_i
$uptime=%x(cat /proc/uptime | cut -d"." -f1).to_i
$boot_time=$now-$uptime
%x(dmesg).split(/\r?\n/).each { |line|
line.chomp!
if line =~ /\[\s*(\d+)\.(\d+)\]\s*(.*)/i
t=Time.at($boot_time+$1.to_i)
ts=t.strftime("%Y-%m-%d %H:%M:%S")
puts "[%s] >> %s" % [ ts, $3 ]
end
}
Just wanted to point out that none of the above provided scripts working.
String found where operator expected at ./dmesg_checker.pl line 31, near "OQ "\n""
(Do you need to predeclare OQ?)
Missing comma after first argument to join or string function at ./dmesg_checker.pl line 31, near "@dmesg_new )"
Execution of ./dmesg_checker.pl aborted due to compilation errors.
Traceback (most recent call last):
File "./dmesg_checker.py", line 20, in
_dmesg_line_regex = re.compile("^\[(?P<time>\d+\.\d+)\](?P<line>.*)$")
File "/usr/lib/python2.7/re.py", line 190, in compile
return _compile(pattern, flags)
File "/usr/lib/python2.7/re.py", line 244, in _compile
raise error, v # invalid expression
sre_constants.error: unknown specifier: ?P&
yes ,So is mine.
dmesg -T works on CentOS 7.3, thanks to all for useful comments.