如何添加将使用 dmesg 读取的消息?

cal*_*doa 49 linux dmesg syslog

我正在尝试在我的 dmesg 输出中编写一些自定义消息。我试过:

logger "Hello"
Run Code Online (Sandbox Code Playgroud)

但这不起作用。它退出没有错误,但没有“Hello”出现在以下输出中:

dmesg
Run Code Online (Sandbox Code Playgroud)

我使用的是 Fedora 9,似乎没有运行 syslogd/klogd 守护进程。但是,我所有的内核消息都成功写入了 dmesg 缓冲区。

任何的想法?

wvd*_*hel 127

您可以以 root 身份写入/dev/kmsg以打印到内核消息缓冲区:

 fixnum:~# echo Some message > /dev/kmsg
 fixnum:~# dmesg | tail -n1
 [28078118.692242] Some message
Run Code Online (Sandbox Code Playgroud)

我已经在我的服务器和嵌入式 Linux 设备上对此进行了测试,并且在两者上都可以使用,所以我假设它几乎可以在任何地方使用。

  • 实际上,这是因为输入重定向是由您的 shell 处理的,它没有以提升的权限运行。尝试运行`echo Some message | sudo tee /dev/kmesg` 作为非 root 用户。 (19认同)
  • 那个有效。谢谢,有趣。顺便说一下,它的 `kmsg` 不是 `kmesg`,但我也混淆了带有 e 的 `dmesg`! (5认同)
  • 比编译内核模块容易得多 (4认同)
  • 为了在系统日志中正确格式化,请务必添加优先级(用角度分隔)和标签(用冒号分隔)。`echo '<4>Foo:消息' | sudo tee /dev/kmsg` (3认同)

Kyl*_*ndt 40

dmesg显示内核缓冲区中的内容,而logger用于syslogd. 我认为如果您想将内容打印到内核缓冲区中,您将需要创建一个使用printk()内核函数的驱动程序。如果你只是想要它/var/log/messages,那么通过“正常”设置,我认为你所做logger的已经很好了。

驱动程序的最基本示例printk()是:

你好ç:

#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");

}
Run Code Online (Sandbox Code Playgroud)

生成文件:

obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
Run Code Online (Sandbox Code Playgroud)

然后:

$ make
$ sudo insmod hello.ko
$ dmesg | tail -n1
 [7089996.746366] Hello world
Run Code Online (Sandbox Code Playgroud)

http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN121了解更多...


cal*_*doa 13

基于上面凯尔的模块:


#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");
Run Code Online (Sandbox Code Playgroud)

要从用户空间执行 printk:

echo "Hello" > /proc/printk
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 5

@Calandoa 的答案不再适用于内核 +3.10。结合他的代码和我在这里找到的示例代码。然后改进代码质量......

代码保存到 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);
Run Code Online (Sandbox Code Playgroud)

使用此 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
Run Code Online (Sandbox Code Playgroud)