Come aggiungere un messaggio che verrà letto con dmesg?


44

Sto cercando di scrivere alcuni messaggi personalizzati nel mio output di dmesg. Provai:

logger "Hello"

Ma questo non funziona. Esce senza errori, ma nessun "Hello" appare nell'output di:

dmesg

Sto usando un Fedora 9 e sembra che non ci sia un demone syslogd / klogd in esecuzione. Tuttavia, tutti i miei messaggi del kernel sono scritti con successo nel buffer dmesg.

Qualche idea?

Risposte:


37

dmesgmostra cosa c'è nel buffer del kernel, mentre loggerè per syslogd. Penso che se si desidera stampare elementi nel buffer del kernel, sarà necessario creare un driver che utilizza la printk()funzione kernel. Se lo vuoi solo /var/log/messages, quindi con una configurazione "normale" penso che quello che hai fatto loggersia già a posto.

L'esempio più semplice di un driver con printk()sarebbe:

Ciao 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

Poi:

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

http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN121 per ulteriori informazioni ...


Ho ricevuto un errore, dal momento che hai inserito degli spazi prima make -C ...nel Makefile anziché in una Scheda, quindi la copia dei contenuti sopra del Makefile non funziona - più qui . Mi sembra di non poterlo aggiungere in una modifica ... Grazie, ottima risposta.
Wilf,

107

È possibile scrivere come root /dev/kmsgper stampare sul buffer dei messaggi del kernel:

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

Ho provato questo sul mio server e su un dispositivo Linux incorporato, e funziona su entrambi, quindi suppongo che funzioni praticamente ovunque.


1
Interessante che in Ubuntu funzioni come root ma non con sudo. Uno ha effettivamente bisogno di diventare root.
dotancohen,

15
In realtà, è perché il reindirizzamento dell'input è gestito dalla shell, che non è in esecuzione con diritti elevati. Prova a eseguire echo Some message | sudo tee /dev/kmesgcome non root.
wvdschel,

3
Che funzioni. Grazie, interessante A proposito, kmsgnon è kmesgma mi confondo anche con dmesgchi ha l'e!
dotancohen

4
Molto più semplice della compilazione del modulo del kernel
e271p314

13

Basato sul modulo di Kyle sopra:


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

Per eseguire un printk dallo spazio utente:

echo "Hello" > /proc/printk

1
Funziona solo con kernel Linux <3.10. Vedi la mia risposta per una nuova alternativa.
Kevin

5

La risposta di @Calandoa non funziona più per il kernel +3.10. Combinato il suo codice e il codice di esempio che ho trovato qui . Quindi migliorato la qualità del codice ...

Codice salvato in 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);

Usa questo 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

Sulla base della risposta di Kyle, ecco un breve tutorial che mostra come fare proprio questo.


2

Ho pensato di andare avanti e includere un esempio completo di qualcosa che le persone possono semplicemente compilare ed eseguire per quelli che non sono così abili con C in base alla risposta di @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);
};

Per eseguire, salvare quanto sopra come kmsg.c e gcc kmsg.c -o kmsg; sudo ./kmsg "stringa che si desidera aggiungere a / dev / kmsg"


0

Volevo solo alcuni messaggi di debug rapidi in un demone scritto da qualcun altro in un kernel rispettato. Ho riscontrato un errore di compilazione durante il tentativo di utilizzo printk, poiché <linux/module.h>non è stato possibile includerlo. Piuttosto, combatti con quello in modo eccessivo (per farlo nel modo giusto) ho imbrogliato e usato la seguente soluzione pigra, ma funzionale di 5 minuti:

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 ); }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.