संदेश कैसे जोड़ें जो dmesg के साथ पढ़ा जाएगा?


44

मैं अपने dmesg आउटपुट में कुछ कस्टम संदेश लिखने की कोशिश कर रहा हूं। मैंने कोशिश की:

logger "Hello"

लेकिन यह काम नहीं करता है। यह त्रुटि के बिना बाहर निकलता है, लेकिन कोई भी "हैलो" का आउटपुट नहीं दिखता है:

dmesg

मैं एक Fedora 9 का उपयोग कर रहा हूं, और ऐसा लगता है कि कोई syslogd / klogd डेमॉन नहीं चल रहा है। हालाँकि, मेरे सभी कर्नेल संदेश सफलतापूर्वक dmesg बफर में लिखे गए हैं।

कोई उपाय?

जवाबों:


37

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

}

makefile:

obj-m += hello.o

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

फिर:

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

http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN121 अधिक के लिए ...


मुझे एक त्रुटि मिली, क्योंकि आपने make -C ...टैब के बजाय मेकफाइल में पहले स्थान रखा है , इसलिए मेकफाइल की उपरोक्त सामग्री को कॉपी करने से काम नहीं होता है - यहाँ और । मैं इसे संपादित करने में असमर्थ होने के लिए प्रकट होता हूं ... वैसे, बहुत बढ़िया जवाब।
विल्फ

107

आप कर सकते हैं, रूट के रूप में, /dev/kmsgकर्नेल संदेश बफ़र पर प्रिंट करने के लिए लिखें :

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

मैंने इसे अपने सर्वर और एक एम्बेडेड लिनक्स डिवाइस पर परीक्षण किया है, और यह दोनों पर काम करता है, इसलिए मैं बस यह मानने जा रहा हूं कि यह हर जगह बहुत काम करता है।


1
दिलचस्प है कि उबंटू में, यह रूट के रूप में काम करता है लेकिन सुडो के साथ नहीं। वास्तव में जड़ बनने की जरूरत है।
डॉटनचेन

15
दरअसल, ऐसा इसलिए है क्योंकि इनपुट पुनर्निर्देशन आपके शेल द्वारा संभाला जाता है, जो उन्नत अधिकारों के साथ नहीं चल रहा है। echo Some message | sudo tee /dev/kmesgगैर-रूट के रूप में चलाने का प्रयास करें ।
wvdschel

3
यह काम करता है। धन्यवाद, दिलचस्प। वैसे, इसका kmsgनहीं, kmesgलेकिन मैं भी भ्रमित करता हूं dmesgजिसके पास ई है!
डॉटंचोहेन

4
कर्नेल मॉड्यूल संकलित करने की तुलना में बहुत आसान है
e271p314

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

उपयोगकर्ता स्थान से एक प्रिंट करने के लिए:

echo "Hello" > /proc/printk

1
यह लिनक्स कर्नेल <3.10 के लिए ही काम करता है। एक नए विकल्प के लिए मेरा जवाब देखें।
केविनफ

5

@ कैलेंडोआ का जवाब अब कर्नेल +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);

इस 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

काइल के जवाब के आधार पर, यहां एक त्वरित ट्यूटोरियल दिखाया गया है कि यह कैसे करना है।


2

यह पता लगाया कि मैं आगे जाऊंगा और इसमें एक पूर्ण विकसित उदाहरण शामिल होगा, जिसे लोग केवल उन लोगों के लिए संकलित और चला सकते हैं, जो @BuvinJ के उत्तर के आधार पर C के साथ कुशल नहीं हैं।

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

Kmsg.c और gcc kmsg.c -o kmsg; sudo ./kmsg "स्ट्रिंग को आप / dev / kmsg में जोड़ना चाहते हैं, के रूप में उपरोक्त को चलाने के लिए"


0

मैं बस एक त्वरित कंपाइल किए गए कर्नेल में किसी अन्य द्वारा लिखित डेमन में कुछ त्वरित डिबगिंग संदेश चाहता था। मैं एक संकलित त्रुटि का उपयोग करने की कोशिश कर रहा था printk, क्योंकि <linux/module.h>इसमें शामिल नहीं किया जा सकता था। बल्कि उस अत्यधिक के साथ लड़ाई (सही तरीके से करने के लिए) मैंने धोखा दिया और निम्न आलसी का उपयोग किया, लेकिन कार्यशील 5% कार्य:

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 ); }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.