有没有办法确定哪个进程正在重新启动服务器?

有没有办法确定哪个进程正在重新启动服务器?

我有一个 kvm 虚拟机,它似乎会随机重新启动。我在 syslog 中没有看到任何有关重新启动、关闭、错误、核心转储、恐慌等的信息。主机上的 libvirtd 日志中也没有错误,qemu 日志中也没有错误,主机上也没有任何错误。

似乎某个随机进程可能正在调用虚拟机内的重新启动系统调用?我能想到的就只有这些了...

我如何确定是什么原因造成的?操作系统是Debian。

答案1

如果您不介意接触 C 代码,那么您可以编写一个简单的内核模块来拦截重新启动/关闭调用并通过printk().

这个答案可能是一个好的开始。要了解谁在调用您修改后的处理程序,请查看这个

测试代码

我尝试开发上面的提示,并提出了以下代码。

在我自己的家庭系统(Ubuntu 22.04-LTS)上,它确实编译并安装了内核模块,并且似乎可以使用一些符号: 例如__do_sys_swapon

Dec 15 22:38:51 mintaka kernel: [82534.879652] __do_sys_swapon called by PID 5381 (swapon)

但是 中似乎有几个类似重新启动的调用/proc/kallsyms,所以恐怕您需要几个 kprobe,或者需要相当多的试验和错误。如果我从提示符中__do_sys_reboot调用,似乎不会被记录。reboot

#include <linux/module.h>
#include <linux/printk.h>
#include <linux/kprobes.h>

MODULE_LICENSE("GPL");

/**
 * Pre handler
 * @return int  unless you're a kprobe geek
 */
static noinline int handler(struct kprobe *p, struct pt_regs *regs) {
    struct task_struct *task = current;
    printk(KERN_EMERG "%s called by PID %d (%s)\n", p->symbol_name, (int)task->pid, task->comm);
    return 0;
}

// Verify that the symbol name is present in /proc/kallsyms
static struct kprobe kp = {
    .symbol_name    = "__do_sys_reboot",
    .pre_handler    = handler
};
/**
 * Module initialization
 *
 * @returns int
 */

int init_module(void) {
    int ret;
    printk(KERN_INFO "loading whistlebooter\n");
    // register_kprobe ultimately returns e.g. arch_copy_kprobe() which succeeds with 0
    ret = register_kprobe(&kp);
    if (ret < 0) {
        if (-2 == ret) {
            printk(KERN_INFO "register_kprobe did not find the requested symbol\n");
        } else {
            printk(KERN_INFO "register_kprobe failed with code %d\n", ret);
        }
    } else {
        printk(KERN_INFO "kprobe registered at addr=%p for '%s'\n", kp.addr, kp.symbol_name);
    }
    return 0;
}

/**
 * @returns void
 */
void cleanup_module(void) {
    printk(KERN_INFO "unloading whistlebooter\n");
    unregister_kprobe(&kp);
}

生成文件

# vim: tabstop=4 sw=4 noexpandtab
obj-m += mymodule.o
PWD := $(CURDIR)

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

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

要编译,只需运行“ make”。

相关内容