+ -
当前位置:首页 → 问答吧 → 如何在伪终端(通过ssh远程登录)显示内核打印信息

如何在伪终端(通过ssh远程登录)显示内核打印信息

时间:2010-07-13

来源:互联网

我通过ssh远程登录linux主机,但内核打印信息却只能打印在主机的控制台上,如何让打印信息在我的个人电脑登录终端上打印啊,希望高手赐教。

作者: linuxer_lhw   发布时间: 2010-07-13

如果打印启动信息的话,可以考虑修改内核参数

作者: Godbach   发布时间: 2010-07-13

回复 Godbach


    不是启动信息,自己编写的内核模块的printk信息,比如模块手动加载或运行时产生的信息。以前做嵌入式开发的时候,修改内核参数可以把信息打印到串口终端上,不知道能不能用什么方法打印到这种远程登录的客户端上,有个netconsole方法不知道行不行

作者: linuxer_lhw   发布时间: 2010-07-13

netconsole主要是配置把内核信息传输到其他机器上的日志文件中。

作者: Godbach   发布时间: 2010-07-13

既然有终端登陆,查看日志也是一种不错的方式啊

作者: Godbach   发布时间: 2010-07-13

/etc/issue.net 这个吧

作者: vermouth   发布时间: 2010-07-13

我有个思路,不知道可不可行,明天试试

作者: lmarsin   发布时间: 2010-07-13

回复 Godbach


    我的终端是windows下的,没法看日志。呵呵。其实一般可以查看dmesg 或者/var/log/message ,主要是有时后oops死机时要查看瞬间的信息。

作者: linuxer_lhw   发布时间: 2010-07-13



QUOTE:
回复  Godbach


    我的终端是windows下的,没法看日志。呵呵。其实一般可以查看dmesg 或者/var/log/ ...
linuxer_lhw 发表于 2010-07-13 19:25



查看日志看文件/var/log/messages就可以了。
你通过终端同样也可查看该文件啊

作者: Godbach   发布时间: 2010-07-13

回复 lmarsin


    如果可以的话给大家说说哈。谢谢

作者: linuxer_lhw   发布时间: 2010-07-13

回复 Godbach


    没死机可以,但调试时出oops一般就死机了就没法看了,重启后就没了。死机前oops倾泄出来的信息会打印到控制台上,但我每次都得跑到服务器那边看,很麻烦,所以我想能不能将prink信息直接打印到本地机器的终端上,我本地机器是windows,通过SecureCRT远程登录

作者: linuxer_lhw   发布时间: 2010-07-13

那就用netconsole传递到另外一台Linux上好了。
BTW,你的系统重启之后就没有以前的日志信息了吗,用的是硬盘吗?

作者: Godbach   发布时间: 2010-07-13

解决办法1:dmesg


解决方法2:
void print_string(char *str)
{
    struct tty_struct *my_tty;

    my_tty = current->tty;

    if (my_tty != NULL) {

                                       (*(my_tty->driver).write)( my_tty, 0, str,strlen(str));
                                       (*(my_tty->driver).write)( my_tty, 0, "" "", 2);
    }
}

作者: unbutun   发布时间: 2010-07-13

你也可以再封一层,用va_start封成printf的形式,就更完美了

作者: unbutun   发布时间: 2010-07-13

本帖最后由 lmarsin 于 2010-07-14 15:26 编辑

回复 linuxer_lhw


    花了半天的时间,对昨天的想法做了验证,基本实现了,并贴上代码。以下代码只是验证我的思路而已,请大牛们拍砖。

我们知道,当通过ssh连接主机时,linux会在/dev/pts/下创建对应的终端设备文件,通过写此文件即可向对应的终端发送信息,以下图示例:
下载 (57.01 KB)
2010-07-14 14:52

首先通过SecureCRT登录到linux主机,可以看到/dev/pts下有设备文件0。
然后,在虚拟机的命令行上输入echo "123456789" > /dev/pts/0 回车后,便在ssh的虚拟终端上输出123456789。

我们知道printk最终是输出到console,只要我们创建一个自己的console并注册到系统中,这样当调用printk时,我们可以很容易的得到printk输出的信息,此时再将此信息输向到/dev/pts/xxx即可。

代码 ptyconsole.rar (1.98 KB)
下载次数: 10
2010-07-14 14:58


在虚拟机的窗口操作效果如下:通过printk打印的内容同时输出到了终端上。
下载 (79.75 KB)
2010-07-14 15:01

作者: lmarsin   发布时间: 2010-07-14

多谢lmarsin兄的分享。刚刚测试了一下,是可以打印远程登录的终端上。
不过我本地出现了一下错误,应该是oops信息:


QUOTE:
ptyfile:/dev/pts/1
                                                  np.pty_file:cd068900
                                                                      open file: 0
                                                                                  BUG: sleeping function called from invalid context at include/asm/uaccess_32.h:512
                       in_atomic():0, irqs_disabled():1
                                                       Pid: 5112, comm: insmod Not tainted 2.6.24.4 #2
                                                                                                       [<c01259f8>] __might_sleep+0xa4/0xa9
                                                                                                                                            [<c01ec615>] copy_from_user+0x2d/0x60
                                     [<c02284a7>] tty_write+0x132/0x1c7
                                                                        [<c022c585>] write_chan+0x0/0x1b3
                                                                                                          [<c017389a>] vfs_write+0xac/0x12c
                                                                                                                                            [<e0a0a04b>] write_msg+0x4b/0x73 [ptyconsole]
                                             [<e0a0a000>] write_msg+0x0/0x73 [ptyconsole]
                                                                                          [<c01289ba>] __call_console_drivers+0x51/0x5b
                                                                                                                                        [<c0128ad7>] call_console_drivers+0xb2/0xd4
                                       [<c01290f4>] release_console_sem+0x70/0xb0
                                                                                  [<e0a0a12a>] init_ptyconsole+0x40/0x54 [ptyconsole]
                                                                                                                                      [<c01461df>] sys_init_module+0x91/0x11b
                                 [<c0104dc6>] sysenter_past_esp+0x5f/0x85
                                                                          =======================
                                                                                                 ptyconsole: network logging started

作者: Godbach:   发布时间: 2010-07-14

本帖最后由 lmarsin 于 2010-07-14 15:38 编辑

回复 Godbach

你的系统打开了CONFIG_DEBUG_SPINLOCK_SLEEP功能,应该是在中断或软中断上下文的输出过程中睡眠了,printk在中断或软中断以及进程上下文中都可以被调用。
代码只是验证了我的思路,没有进行中断调用的测试。

作者: Godbach   发布时间: 2010-07-14

另外,lmarsin兄测试发生oops的情况了吗。如果oops发生了,可能一些write操作都不能保证了,还有可能输出到终端吗

作者: lmarsin   发布时间: 2010-07-14

本帖最后由 lmarsin 于 2010-07-14 15:43 编辑

回复 Godbach
这种情况没有测试。

对于你上面发生的问题,可以在write_msg函数中,注释掉
local_irq_save(flags);
local_irq_restore(flags);
之后测试下看看

static void write_msg(struct console *con, const char *msg, unsigned int len)
{
#if USE_SYS_CALL
        unsigned long flags;
        mm_segment_t old_fs;
               
        old_fs = get_fs();
        set_fs(KERNEL_DS);
        sys_write(np.pty_fd, msg, len);
        set_fs(old_fs);
#else
        unsigned long flags;
        ssize_t ret = -EBADF;
        mm_segment_t old_fs;
               
        if (np.pty_file) {       
                old_fs = get_fs();
                set_fs(KERNEL_DS);
                       
                loff_t pos = np.pty_file->f_pos;
                ret = vfs_write(np.pty_file, msg, len, &pos);
                np.pty_file->f_pos = pos;
               
                set_fs(old_fs);
        }
#endif
}

作者: Godbach   发布时间: 2010-07-14

你的代码中定义USE_SYS_CALL为0.也就是不走这个分支吧。
注释掉了local_irq_save(flags);
对应的local_irq_restore(flags);也需要注释掉啊

作者: lmarsin   发布时间: 2010-07-14

回复 Godbach


    那是应该的。

本来我是直接调用系统调用的,但不知为何加载时链接不到sys_open符号,所以用filp_open等方法了,用USE_SYS_CALL来区分两种方法。

作者: Godbach   发布时间: 2010-07-14

用filp_open挺好的。

作者: lmarsin   发布时间: 2010-07-14

改过后的这块代码为:
  1. static void write_msg(struct console *con, const char *msg, unsigned int len)
  2. {
  3. #if USE_SYS_CALL
  4.         unsigned long flags;
  5.         mm_segment_t old_fs;
  6.                
  7. //        local_irq_save(flags);
  8.         old_fs = get_fs();
  9.         set_fs(KERNEL_DS);
  10.         sys_write(np.pty_fd, msg, len);
  11.         set_fs(old_fs);
  12.        
  13. //        local_irq_restore(flags);       
  14. #else
  15.         unsigned long flags;
  16.         ssize_t ret = -EBADF;
  17.         mm_segment_t old_fs;
  18.                
  19.         if (np.pty_file) {
  20.                 local_irq_save(flags);
  21.                
  22.                 old_fs = get_fs();
  23.                 set_fs(KERNEL_DS);
  24.                        
  25.                 loff_t pos = np.pty_file->f_pos;
  26.                 ret = vfs_write(np.pty_file, msg, len, &pos);
  27.                 np.pty_file->f_pos = pos;
  28.                
  29.                 set_fs(old_fs);
  30.                
  31. //                local_irq_restore(flags);
  32.         }
  33. #endif
  34. }
复制代码
加载模块情况为


QUOTE:
[root@localhost ~]# ptyfile:/dev/pts/2
np.pty_file:d59e3780
open file: 0
BUG: sleeping function called from invalid context at include/asm/uaccess_32.h:512
in_atomic():0, irqs_disabled():1
Pid: 6590, comm: insmod Not tainted 2.6.24.4 #2
[<c01259f8>] __might_sleep+0xa4/0xa9
[<c01ec615>] copy_from_user+0x2d/0x60
[<c02284a7>] tty_write+0x132/0x1c7
[<c022c585>] write_chan+0x0/0x1b3
[<c017389a>] vfs_write+0xac/0x12c
[<e0a0a04a>] write_msg+0x4a/0x6f [ptyconsole]
[<e0a0a000>] write_msg+0x0/0x6f [ptyconsole]
[<c01289ba>] __call_console_drivers+0x51/0x5b
[<c0128ad7>] call_console_drivers+0xb2/0xd4
[<c01290f4>] release_console_sem+0x70/0xb0
[<e0a0a126>] init_ptyconsole+0x40/0x54 [ptyconsole]
[<c01461df>] sys_init_module+0x91/0x11b
[<c0104dc6>] sysenter_past_esp+0x5f/0x85
=======================
ptyconsole: network logging started

作者: Godbach   发布时间: 2010-07-14

本帖最后由 lmarsin 于 2010-07-14 15:57 编辑

回复 Godbach


    好像你还漏改了一个地方,你贴代码的20行

作者: Godbach   发布时间: 2010-07-14

回复 lmarsin
惭愧,这个关键的地方漏掉了。

作者: lmarsin   发布时间: 2010-07-14

改了之后,好像还和前面的信息一样:


QUOTE:
[root@localhost ~]# ptyfile:/dev/pts/2
np.pty_file:c6d48b40
open file: 0
BUG: sleeping function called from invalid context at include/asm/uaccess_32.h:512
in_atomic():0, irqs_disabled():1
Pid: 7481, comm: insmod Not tainted 2.6.24.4 #2
[<c01259f8>] __might_sleep+0xa4/0xa9
[<c01ec615>] copy_from_user+0x2d/0x60
[<c02284a7>] tty_write+0x132/0x1c7
[<c022c585>] write_chan+0x0/0x1b3
[<c017389a>] vfs_write+0xac/0x12c
[<e0a2a041>] write_msg+0x41/0x66 [ptyconsole]
[<e0a2a000>] write_msg+0x0/0x66 [ptyconsole]
[<c01289ba>] __call_console_drivers+0x51/0x5b
[<c0128ad7>] call_console_drivers+0xb2/0xd4
[<c01290f4>] release_console_sem+0x70/0xb0
[<e0a2a11d>] init_ptyconsole+0x40/0x54 [ptyconsole]
[<c01461df>] sys_init_module+0x91/0x11b
[<c0104dc6>] sysenter_past_esp+0x5f/0x85
=======================
ptyconsole: network logging started

作者: Godbach   发布时间: 2010-07-14

我这里设置USE_SYS_CALL为1的,编译时也提示sys_open和sys_write的问题

作者: Godbach   发布时间: 2010-07-14

我这边只提示sys_open

作者: Godbach   发布时间: 2010-07-14

回复 Godbach


    系统会挂掉吗?

作者: lmarsin   发布时间: 2010-07-14

系统不会挂掉。就是报错的信息还是一样的。

作者: lmarsin   发布时间: 2010-07-14