Вопрос или проблема
Я столкнулся с неожиданной перезагрузкой системы, и у меня не осталось vmcore.
Поэтому я хочу отслеживать, когда произошла перезагрузка ядра и кто её инициировал.
Как я думал ранее, когда я ввожу команду reboot
, тогда будет вызван SYSCALL_DEFINE4(reboot)
, после чего ядро переходит в функцию kernel_restart
.
Но на самом деле, когда я использовал kprobe для отслеживания kernel_restart
и ввел reboot
, ничего не было зафиксировано —- я уже тестировал несколько других функций ядра, таких как do_sys_open
и ksys_umount
, и они все работали нормально, так что, по крайней мере, использование kprobe у меня не ошибочно.
Теперь мне интересно, существует ли какой-либо другой способ в ядре для вызова перезагрузки?
Хорошо, я думаю, что нашел ответ.
Похоже, что когда я ввожу reboot
, система сначала посылает сигналы для завершения всех других процессов, даже rsyslogd и systemd-journald, поэтому я не могу найти никаких записей в сообщениях journalctl.
Я использую kprobe для отслеживания __do_sys_open
(которая должна быть системным вызовом для перезагрузки) и добавляю панику при вызове, и теперь я вижу, что перезагрузка вызывается в vmcore-dmesg под /var/crash
.
К сожалению, процесс в vmcore-dmesg всегда reboot
, даже если я использую скрипты оболочки для вызова перезагрузки, и другие потоки не могут быть найдены в vmcore.
Но по крайней мере теперь я знаю, что __do_sys_reboot
— это способ, которым ядро выполняет перезагрузку.
Ответ или решение
Для обнаружения перезагрузки системы и определения, какой процесс инициировал её, действительно можно применить несколько подходов.
-
Использование kprobes: Как вы уже заметили, функция
kernel_restart()
может не зафиксироваться из-за того, что она вызывает различные процессы перед фактической перезагрузкой. Более подходящим является отслеживание функции__do_sys_reboot()
, как вы уже выяснили. Это позволяет фиксировать вызов перезагрузки с более ранними данными о процессе. Добавьте kprobe для функции__do_sys_reboot()
:static struct kprobe kp = { .symbol_name = "__do_sys_reboot", }; static int handler_pre(struct kprobe *p, struct pt_regs *regs) { pr_info("Reboot initiated by PID: %d\n", current->pid); return 0; // Возвращаем 0 для продолжения } static int __init kprobe_init(void) { register_kprobe(&kp); return 0; } static void __exit kprobe_exit(void) { unregister_kprobe(&kp); } module_init(kprobe_init); module_exit(kprobe_exit);
Это позволит вам отследить, какой процесс инициировал перезагрузку.
-
Анализ системных логов: Как вы отметили, системные процессы, такие как
rsyslogd
иsystemd-journald
, закрываются до завершения перезагрузки, и поэтому информация может быть потеряна. Прежде чем вы будете инициировать перезагрузку, можно настроить систему так, чтобы она максимально сохраняла журналы. Для этого вы можете использовать механизмы ‘persistent logging’ вsystemd
илиrsyslog
, чтобы обеспечить сохранность логов во время перезагрузки. -
Использование /var/log/wtmp или /var/log/lastlog: Эти файлы могут давать информацию о том, кто или что инициировало перезагрузку. Введите команду
last reboot
для отображения списка последних перезагрузок. -
Обработка сигналов: Важно отметить, что не только команда
reboot
, но также командуshutdown
, или SIGINT/SIGTERM сигналы могут инициировать перезагрузку системы. Вам стоит отслеживать обработку этих сигналов также. -
Настройка системы для сохранения состояния: Если ваша система поддерживает
kexec
, вы можете использовать его для перезагрузки на новый ядро, сохраняя контекст текущего ядра, что может помочь в отладке. -
Настройка watchdog-таймеров: Вы можете использовать аппаратный watchdog для мониторинга состояния системы и ее перезагрузки. Это может помочь вам определить, произошла ли перезагрузка из-за системной ошибки или сбоя.
-
Сбои и диагностика: Убедитесь, что у вас активирован
kdump
для сохранения дампов ядра, что поможет в дальнейшей диагностике, если произошла паника или сбой системы.
Таким образом, комбинация из вышеупомянутых методов поможет вам точно определить, когда и по какой причине произошло перезагрузка системы.