154

I want to do something like

dmesg | tail -f

but it doesn't work:

I use Mac OS X v10.6.7 (Snow Leopard). By doing that, tail will exit, instead of monitoring the output.

I wonder if there is a way to do it, or an equivalent command.

P.S., I don't think a while loop will be a good enough idea.

  • 4
    On Mac OSX, that file is /var/log/kernel.log – Anonymous May 26 '11 at 22:01
  • 1
    @Anonymous 2: Unfortunately, kernel.log does not contain the same output as dmesg. For example, for a damaged drive, file read errors in dmesg specify exactly which file could not be read, while kernel.log unfortunately provides only the less-than-helpful notice: disk0s2: I/O error. – Ivan Vučica Oct 25 '11 at 17:41
  • 5
    Since linux 3.5, you can do dmesg -w. – Doug Richardson Sep 12 '14 at 16:10
  • 2
  • 1
    You can do sudo dmesg >> "$TMPDIR/dmesg.log"; tail -f "$TMPDIR/dmesg.log" on Mac. – Mint Oct 18 '19 at 5:58

12 Answers 12

142

You are probably looking for some combination of messages from various log files. Try:

tail -f /var/log/{messages,kernel,dmesg,syslog}

…to get a pretty good overview of the system. If you want more or less than that, research what log file the messages you want to see are being placed in.

Also look into using multitail to file and color code and filter multiple log files at once.

Edit: This wasn't very relevant when I answered this, but as this page gets a lot of hits I'm thought it worth mentioning that newer systems running systemd have this.

dmesg -w
| improve this answer | |
  • 5
    Thanks for the heads-up re: multitail. Looks interesting. In the case of OS X it'll be something like: tail -f /var/log/{system.log,kernel.log}. – boehj May 27 '11 at 3:21
  • 2
    system.log and kernel.log do not contain the exact output of dmesg on OS X. For example, for a damaged drive, file read errors in dmesg specify exactly which file could not be read, while kernel.log unfortunately provides only the less-than-helpful notice: disk0s2: I/O error. – Ivan Vučica Oct 25 '11 at 17:45
  • 3
    For the record, this answer doesn't work on OS X Mavericks (10.9) or Arch Linux. – Elle Mundy Dec 24 '13 at 15:31
  • @Dan On Arch you probably don't have a syslog daemon installed or its service enabled. I've noticed that isn't part of the base package set even though it's pretty fundamental. OSX is BSD based and has different paths for a lot of things. You'll need to figure out how and where your system handles logging and adjust. My answer is pretty generic and covers most FHS based distros with syslog enabled, but there are also lots of variant implementations. – Caleb Dec 24 '13 at 15:38
  • 1
    ++ on the edit. – pstanton May 8 '18 at 23:59
56

Just make it @#$%ing work

  1. You want to print output of dmesg, constantly, immediately
  2. Dmesg is printing the kernel ring buffer (see man dmesg)
  3. The kernel ring buffer is a special proc file, /proc/kmsg (see man proc)
  4. Read /proc/kmsg directly, ie cat /proc/kmsg.

Now, if you read the friendly proc manual, it'll sternly warn you to let only one user (who must be privileged) read /proc/kmsg at a time. Whatever syslog implementation you have should be doing this, and presumably it works with dmesg. I dunno, I'm out of my league here, just paraphrasing the manual. So while this is the "just make it @#$%ing work" way, consider the next couple methods first.

Man page approved: watch + dmesg

On one linux box I use with systemd init*, dmesg.log isn't written to very often, perhaps not at all? The best way I found to read the kernel log buffer continuously is with watch. Something like this should get you started (adjust for how many lines fit in your terminal):

watch 'dmesg | tail -50'

watch + dmesg + daemon + tail -f

A more convoluted solution might use watch to write dmesg output to file, which you could then tail -f. You'd probably want this running as a daemon. A proper daemon would also gzip and rotate logs. The following bash code is untested, unworking, and only intended to convey an idea. @Brooks Moses's answer has a working version.

watch 'dmesg >> /var/log/dmesg.log | tail -1'

* tangent, cause this is a question about an apple desktop os: when systemd is around, don't bother with dmesg; use journalctl -xf (maybe w/ -n 100 to also show the previous 100 lines)

| improve this answer | |
  • 1
    OS X does not have /proc, however the rest of your answer is applicable. watch can be installed from MacPorts: macports.org – Ivan Vučica Oct 25 '11 at 17:44
  • @Ivan Vučica Ah, good to know. Wonder where OSX represents the kernel ring buffer.. – djeikyb Oct 27 '11 at 22:49
  • 2
    Looks like it's directly in the kernel memory. Source code for Apple's dmesg implementation: opensource.apple.com/source/system_cmds/system_cmds-230.7/… Quick Googling doesn't mention anything about it being represented in the filesystem :/ – Ivan Vučica Oct 28 '11 at 9:24
51

On Linux, since kernel kernel 3.5.0 you can use:

dmesg -w

Also on systems with systemd you can use:

journalctl -kf
| improve this answer | |
  • 6
    dmesg -w is the absolutely nicest solution. Unfortunately, even Ubuntu 14.04 doesn't seem to be ready for this because the user space tool doesn't support it yet. – Daniel Alder Aug 25 '14 at 7:19
  • 1
    This answer definately deserves more upvotes now. – m4tx May 3 '15 at 11:29
  • 2
    yes, this is a nice little nugget. can be made human readable with: dmesg -wH – faustus Aug 26 '15 at 4:58
  • This works on Ubuntu 19.10 (Eoan Ermine). – Peter Mortensen Jan 8 at 2:52
21

Here's a variant on djeikyb's answer that's actually tested, and fixes a couple of bugs.

watch 'sudo dmesg -c >> /tmp/dmesg.log; tail -n 40 /tmp/dmesg.log'

The important trick is that we're doing dmesg -c, which clears the ring buffer after it prints -- thus, each time through we're only printing what's new since the last time.

You'll need to be root to do that, thus the sudo. There's also a bugfix; instead of trying to both dump the output to a file and pipe it to tail (which doesn't work), we're just reading from the newly-written file.

We could do just dmesg > /tmp/dmesg.log and overwrite the whole file each iteration, but that's a lot of I/O and also risks losing the file if the computer crashes in the middle of an overwrite.

You could also do something similar that's more closely like tail -f with a while loop that executes dmesg -c and sleep 1 forever (see Ben Harris's answer). However, since this is actually clearing the kernel message buffer as it's running, you may also want to pipe things into a logfile in case you want them later.

| improve this answer | |
7

This may work for you

while true;do sudo dmesg -c;done

Keep in mind that the '-c' flag clears the message buffer into stdout. The 'sudo' is unnecessary if you are root. If you feel this is eating too much of your CPU resource, try adding a 'sleep 1' before the loop is done.

| improve this answer | |
  • watch might be good there, if you are watching the screen all of the time – Seth Robertson May 26 '11 at 22:07
  • 2
    Feel free to cite your sources: linuxforums.org/forum/applications/… – Anonymous May 26 '11 at 22:08
  • 2
    Quick and dirty. Dirty because it only works if you are the only one user doing this. Otherwise each user gets only half of the messages – Daniel Alder Aug 25 '14 at 7:14
  • solves my android adb problem. – PAntoine Apr 27 '16 at 10:25
5

I did this before seeing this post:

#!/usr/bin/env perl

use strict;
use warnings;

# "tail -f" for dmesg
# Keeps last printed line. Anything sorting "gt" will be newer

$|=1;

my $y = '';

while(1) {
    for my $k (`dmesg`) {
        if ($k gt $y) {
            print $k;
            $y = $k;
        }
    }
    sleep 1;
}
exit;
| improve this answer | |
3

I use this alias in /root/.bashrc;

alias dwatch='watch -n 0.1 "dmesg | tail -n $((LINES-6))"'

which follows dmesg and adjusts the lines for whatever terminal it's called in.

| improve this answer | |
3

You might be able to do:

tail -f /var/log/messages
| improve this answer | |
  • 2
    On most systems, the dmesg log file is just a static dump of the dmesg buffer after system boot completes. After that, any new kernel messages usually go into another log file and the dmesg file will stay unchanged until reboot. – Anonymous May 26 '11 at 22:08
  • 7
    I don't know about "most" systems, but none of the GNU Linux systems I admin behave that way. dmesg reports a current set of the latest messages from the kernel, usually specific to the hardware subsystems. – Caleb May 27 '11 at 7:26
3

Here are some ideas for limited environments

Environments such as embedded or pre-boot, where watch, tail, cat, dd and other commands might not be available, might need different gymnastics.

This is what some lightweight Linux distributions do:

while dmesg -c >> /tmp/dmesg.log; do sleep 0.1; done & tail -f /tmp/dmesg.log

It backgrounds the while loop (with &) while tailing the generated output.

If you can't write to /tmp:

mount -t tmpfs - /tmp 

# or 
mount -t ramfs - /tmp 

# or use /dev/shm instead of /tmp - which is available in newer environments

If you don't have tail, you can

cat /tmp/dmesg.log

# or 
dd if=/tmp/dmesg.log 

# or
dd if=/tmp/dmesg.log 2>/dev/null

Or you might be in a busybox environment that doesn't have dmesg linked, then just:

busybox dmesg -c

You might also need to

busybox sleep

instead of sleep

If you don't have sleep:

while dmesg -c; do echo >/dev/null; done 

If you don't have "dmesg":

while sleep 0.1; do cat -v /proc/kmsg; done

This only works if nothing else is reading from here. You might also have a /dev/kmsg.

Bonus tip:

If you don't know what you have, and you don't have "ls", just:

busybox ls

# or simply:

echo *
| improve this answer | |
  • 1
    Please can you explain why this is a solution. – ChrisF Mar 5 '13 at 12:30
  • It's what some distributions do behind the scenes. It polls the kernel ringbuffer and logs it to /tmp/dmesg.log every 0.1 seconds in a background job while it tails that output. Also, it's the only method that will work if you don't have something special running in the background - or if you've killed all background processes and services and you're doing emergency troubleshooting. – Dagelf Jun 5 '13 at 18:07
  • 1
    Seems simpler to use watch – poolie May 31 '17 at 22:39
  • If you have it available :-) sometimes you're in an environment where you don't even have tail... then you can use cat /tmp/dmesg.log, or dd even... If you can't write to /tmp, and can't mount -t tmpfs - /tmp, or ramfs, or write to /dev/shm/... then you can just while dmesg -c; sleep 0.1; do echo >/dev/null; done, if you don't have sleep, just while dmesg -c; do echo >/dev/null; done; Sometimes you don't even have ls... then you just do echo * :-D – Dagelf Jul 7 '17 at 7:17
  • In the answer, not in comments. Can the answer be updated? – Peter Mortensen Jan 8 at 2:44
0

I used this code to look for a special kernel event and piped it a "callback" process:

while true ; do dmesg -c ; sleep .1 ; done \
| grep --line-buffered  -o $pattern \
| ...
| improve this answer | |
0

Under the current Ubuntu (I am using Ubuntu 12.04 (Precise Pangolin)),

tail -f /var/log/syslog
6< <( cat /var/log/syslog |grep -F  'kernel: '; sudo cat /proc/kmsg) cat /dev/fd/6

( the sudo command need sudo privilege )

Please also try another one like: 6< <( dmesg; sudo cat /proc/kmsg) cat /dev/fd/6

| improve this answer | |
-3

This might be useful:

dmesg | tail -f -

pipes the output of dmesg through tail using the - operator as a shortcut to standard output.

| improve this answer | |
  • 2
    This is the code from the question which does not work. – pabouk Jan 15 '14 at 8:39
  • 2
    It doesn't work because dmesg closes output after closing once. tail -f can't change this anymore. – Daniel Alder Aug 25 '14 at 7:12
  • This does not work - it just displays the last 10 lines and stops. Tried on Ubuntu 19.10 (Eoan Ermine). – Peter Mortensen Jan 8 at 2:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.