Como adicionar mensagem que será lida com o dmesg?

42

Eu estou tentando escrever algumas mensagens customizadas na saída do dmesg. Eu tentei:

logger "Hello"

mas isso não funciona. Ele sai sem erro, mas não aparece "Hello" na saída de:

dmesg

Eu estou usando um Fedora 9, e parece que não há um daemon syslogd / klogd rodando. No entanto, todas as minhas mensagens do kernel são gravadas com sucesso no buffer do dmesg.

Alguma ideia?

    
por calandoa 10.05.2010 / 20:24

7 respostas

36

dmesg exibe o que está no buffer do kernel, enquanto logger é para syslogd . Eu acho que se você quiser imprimir coisas no buffer do kernel, você precisará criar um driver que use a função do kernel printk() . Se você quer apenas em /var/log/messages , então, com uma configuração "normal", acho que o que você fez com logger já está bem.

O exemplo mais básico de um driver com printk() seria:

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

Então:

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

link para saber mais ...

    
por 10.05.2010 / 20:30
106

Você pode, como root, gravar em /dev/kmsg para imprimir no buffer de mensagem do kernel:

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

Eu testei isso no meu servidor e em um dispositivo Linux embarcado, e ele funciona em ambos, então vou presumir que funciona praticamente em todos os lugares.

    
por 23.02.2012 / 15:47
13

Baseado no módulo de Kyle acima:


#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] = '
echo "Hello" > /proc/printk
'; 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");

Para fazer uma printk do espaço do usuário:


#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] = '
echo "Hello" > /proc/printk
'; 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");
    
por 11.05.2010 / 11:34
5

@ A resposta de Calandoa não funciona mais para o Kernel +3.10. Combinou o código dele e o código de exemplo que encontrei aqui . Em seguida, melhorou a qualidade do código ...

Código salvo em 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] = '
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
'; 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);

Faça usando este Makefile

#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] = '
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
'; 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);
    
por 25.11.2015 / 21:59
3

Com base na resposta de Kyle, aqui é um rápido tutorial mostrando como fazer isso.

    
por 10.05.2010 / 20:35
2

Pensei em seguir em frente e incluir um exemplo completo de algo que as pessoas podem compilar e executar para aqueles que não são tão habilidosos com C baseados na resposta de @BuvinJ

#include <stdio.h>
#include <string.h>
#include <fcntl.h> // open function
#include <unistd.h> // close function
#include "sys/syscall.h"


int main(); // Let's not worry about this for now

void dmesg( const char *tag, const char *msg, const int len )
{
    const int TAG_LEN=3;
    char buffer[128]={0};
    memcpy( &buffer[0], tag, TAG_LEN );
    memcpy( &buffer[TAG_LEN], msg, len );
    int fd_kmsg = open( "/dev/kmsg", O_WRONLY );
    write( fd_kmsg, &buffer, TAG_LEN+len );
    close( fd_kmsg );
}
void dmesgWarn(  const char *msg, const int len ){ dmesg( "<4>", msg, len ); }
void dmesgInfo(  const char *msg, const int len ){ dmesg( "<6>", msg, len ); }
void dmesgDebug( const char *msg, const int len ){ dmesg( "<7>", msg, len ); }


int main(int argc, char **argv)
{
    int getmysize = strlen(argv[1]);
    printf("%d\n", getmysize);

    printf("To be written: %s\nSize of argument: %d\n", argv[1], getmysize);
    // dmesgWarn dmesgInfo or dmesgDebug
    dmesgDebug(argv[1], getmysize);
};

Para executar, salve as opções acima como kmsg.c e gcc kmsg.c -o kmsg; sudo ./kmsg "string que você deseja adicionar a / dev / kmsg"

    
por 10.05.2019 / 22:29
0

Eu só queria algumas mensagens rápidas de depuração em um daemon escrito por alguém em um kernel cruzado. Eu tive um erro de compilação tentando usar printk , pois <linux/module.h> não pôde ser incluído. Em vez disso, em seguida, batalhar com isso excessivamente (para fazer isso da maneira certa) eu enganei e usei a seguinte solução de 5 minutos preguiçosa, mas funcional:

void dmesg( const char *tag, const char *msg, const int len )
{
    const int TAG_LEN=3;
    char buffer[128]={0};
    memcpy( &buffer[0], tag, TAG_LEN );
    memcpy( &buffer[TAG_LEN], msg, len );
    int fd_kmsg = open( "/dev/kmsg", O_WRONLY );
    write( fd_kmsg, &buffer, TAG_LEN+len );
    close( fd_kmsg );
}
void dmesgWarn(  const char *msg, const int len ){ dmesg( "<4>", msg, len ); }
void dmesgInfo(  const char *msg, const int len ){ dmesg( "<6>", msg, len ); }
void dmesgDebug( const char *msg, const int len ){ dmesg( "<7>", msg, len ); }
    
por 20.03.2019 / 00:54