How to Log Custom Messages to Kernel Ring Buffer (dmesg) in Linux


2 views

The dmesg command displays messages from the Linux kernel ring buffer, which stores kernel-related events during system operation. Unlike user-space logging utilities, this buffer has specific access requirements.

The logger command writes to syslog (user-space), not the kernel ring buffer. When syslogd/klogd aren't running (as in your Fedora 9 case), these messages get lost:

logger "Test message"  # Goes to syslog, not dmesg

Using printk() via /dev/kmsg

The most reliable method is writing directly to /dev/kmsg (requires root):

echo "Hello Kernel" | sudo tee /dev/kmsg
dmesg | tail -n 1  # Verify your message

C Program Example

For programmatic access, use this C code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int kmsg_fd = open("/dev/kmsg", O_WRONLY);
    if (kmsg_fd < 0) {
        perror("Failed to open /dev/kmsg");
        return 1;
    }
    
    const char *msg = "Custom kernel message\n";
    write(kmsg_fd, msg, strlen(msg));
    close(kmsg_fd);
    return 0;
}

For persistent logging, create a simple kernel module:

#include <linux/module.h>
#include <linux/kernel.h>

static int __init hello_init(void) {
    printk(KERN_INFO "Custom module loaded\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk(KERN_INFO "Custom module unloaded\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

After adding messages, verify with:

dmesg -T | tail -n 5  # Show timestamps
journalctl -k      # On systemd systems

If messages don't appear, check:

ls -l /dev/kmsg    # Verify device exists
cat /proc/sys/kernel/printk  # Check logging levels

Remember that:

  • Writing to /dev/kmsg requires root privileges
  • Excessive logging can overwrite important kernel messages
  • In production, consider rate limiting your messages

The dmesg command displays messages from the Linux kernel ring buffer, which contains hardware-related and low-level system messages. Unlike regular system logs handled by syslog, dmesg specifically deals with kernel-space messages.

The logger command you tried sends messages to the syslog facility, not the kernel log buffer. This explains why your message didn't appear in dmesg output. The key differences:

  • logger → syslog (user-space logging)
  • dmesg → kernel ring buffer (kernel-space logging)

Here are several ways to add custom messages to the kernel log buffer:

Using printk from C

The most direct method is using the kernel's printk function. Create a simple kernel module:

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
    printk(KERN_INFO "Hello from kernel module!\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye from kernel module!\n");
}

MODULE_LICENSE("GPL");

Using /dev/kmsg

For a simpler solution without compiling, write directly to /dev/kmsg:

echo "Hello from userspace" | sudo tee /dev/kmsg

Using the dmesg --console-level Option

Some systems allow setting console log level and adding messages:

sudo dmesg --console-level emerg -c "Custom emergency message"

If you're not seeing messages in dmesg, check:

  • Kernel log level settings (cat /proc/sys/kernel/printk)
  • Permission to access /dev/kmsg (typically requires root)
  • Kernel configuration (CONFIG_PRINTK must be enabled)

Here's a bash script that logs custom messages to dmesg with timestamps:

#!/bin/bash

log_to_dmesg() {
    local message="$1"
    local level="${2:-6}" # default to LOG_INFO (6)
    echo "<$level>$message" | sudo tee /dev/kmsg >/dev/null
}

log_to_dmesg "Script started" 5
# Your monitoring code here
log_to_dmesg "Critical event detected" 2
log_to_dmesg "Script completed" 6

For advanced users, you can create kernel hooks that automatically log specific events:

# Example tracepoint (requires kernel headers)
#include <linux/tracepoint.h>

DECLARE_TRACE(my_event,
    TP_PROTO(const char *message),
    TP_ARGS(message)
);

DEFINE_TRACE(my_event);

void log_custom_event(const char *msg)
{
    trace_my_event(msg);
}