42

I am trying to write some custom messages in my dmesg output. I tried:

logger "Hello"

but this does not work. It exits without error, but no "Hello" appears int the output of:

dmesg

I am using a Fedora 9, and it seems that there is no syslogd/klogd daemon running. However, all my kernel messages are succesfully written in the dmesg buffer.

Any idea?

34

dmesg displays what is in the kernel buffer, whereas logger is for syslogd. I think if you want to print things into the kernel buffer you will need to create a driver that uses the printk() kernel function. If you just want it in /var/log/messages, then with a "normal" setup I think what you have done with logger is already fine.

The most basic example of a driver with printk() would be:

hello.c:

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

int init_module(void)
{
    printk(KERN_INFO "Hello world\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye world\n");

}

Makefile:

obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Then:

$ make
$ sudo insmod hello.ko
$ dmesg | tail -n1
 [7089996.746366] Hello world

http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN121 for more...

  • I got an error, since you have put spaces before the make -C ... in the Makefile instead of a Tab, so copying the above contents of the Makefile does not work - more here. I appear to be unable to add this in an edit... Thanks by the way, great answer. – Wilf Jul 11 '14 at 18:17
103

You can, as root, write to /dev/kmsg to print to the kernel message buffer:

 fixnum:~# echo Some message > /dev/kmsg
 fixnum:~# dmesg | tail -n1
 [28078118.692242] Some message

I've tested this on my server and an embedded Linux device, and it works on both, so I'm just going to assume it works pretty much everywhere.

  • 1
    Interesting that in Ubuntu, this works as root but not with sudo. One actually needs to become root. – dotancohen Jun 30 '12 at 8:53
  • 15
    Actually, that's because the input redirection is handled by your shell, which is not running with elevated rights. Try running echo Some message | sudo tee /dev/kmesg as non-root. – wvdschel Jul 4 '12 at 11:56
  • 3
    That works. Thanks, interesting. By the way, its kmsg not kmesg but I also confuse with dmesg which has the e! – dotancohen Jul 4 '12 at 14:55
  • 4
    Much easier than compiling kernel module – e271p314 Mar 3 '14 at 9:22
13

Based on Kyle's module above:


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

static int pk_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
        char string[256];
        count = count < 255 ? count : 255;

        if(copy_from_user(string, buffer, count))
                return -EFAULT;

        string[count] = '\0';        
        printk(string);
        return count;
}


static int __init printk_init(void)
{
        struct proc_dir_entry *pk_file;

        pk_file = create_proc_entry("printk", 0222, NULL);
        if(pk_file == NULL)
                return -ENOMEM;

        pk_file->write_proc = pk_write;
        pk_file->owner = THIS_MODULE;

        return 0;
}

static void __exit printk_cleanup(void)
{
        remove_proc_entry("printk", NULL);
}

module_init(printk_init);
module_exit(printk_cleanup);
MODULE_LICENSE("GPL");

To do a printk from user space:

echo "Hello" > /proc/printk
  • 1
    This works for Linux kernel < 3.10 only. See my answer for a newer alternative. – kevinf Nov 25 '15 at 21:00
5

@Calandoa's answer no longer works for Kernel +3.10. Combined his code, and the example code I found here. Then improved on the code quality...

Code saved to printk_user.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

static ssize_t write_proc(struct file *filep, const char *buffer, size_t count, loff_t *offsetp)
{
    char string[256];
    count = count < 255 ? count : 255;

    if(copy_from_user(string, buffer, count) != 0) {
        return -EFAULT;
    }

    string[count] = '\0';
    printk(string);
    return count;
}

static const struct file_operations proc_fops = {
    .owner = THIS_MODULE,
    .write = write_proc,
};

static int proc_init(void) {
    struct proc_dir_entry *proc_file;
    proc_file = proc_create("printk_user", 0, NULL, &proc_fops);

    if(proc_file == NULL) {
        return -ENOMEM;
    }

    return 0;
}

static void proc_cleanup(void) {
    remove_proc_entry("printk_user", NULL);
}

MODULE_LICENSE("GPL"); 
module_init(proc_init);
module_exit(proc_cleanup);

Make using this Makefile

TARGET = printk_user
obj-m := $(TARGET).o

KERNEL_VERSION=$(shell uname -r)
KDIR = /lib/modules/$(KERNEL_VERSION)/build
PWD = $(shell pwd)

printk:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
    $(MAKE) -C $(KDIR) M=$(PWD) clean
3

Based off of Kyle's answer, here is a quick tutorial showing how to do just that.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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