Хотя в современных Linux-системах ядро отличается достаточно высоким уровнем стабильности, вероятность серьезных системных ошибок, тем не менее, имеется всегда. Когда происходит неисправимая ошибка, имеет место состояние, называемое паникой ядра (kernel panic): стандартный обработчик выводит на экран информацию, которая должна помочь в устранении неисправности, и входит в бесконечный цикл.
Для диагностики и анализа причин сбоев ядра разработчиками компании RedHat был разработан специализированный инструмент — kdump. Принцип его работы можно кратко описать следующим образом. Создается два ядра: основное и аварийное (именно оно используется для сбора дампа памяти). При загрузке основного ядра под аварийное ядро выделяется определенный размер памяти. При помощи kexec во время паники основного ядра загружается аварийное и собирает дамп.
В этой статье мы подробно расскажем о том, как конфигурировать kdump и анализировать с его помощью системные ошибки. Мы рассмотрим особенности работы с kdump в OC Ubuntu; в других дистрибутивах процедуры настройки и конфигурирования kdump существенно отличаются.
Установка и настройка kdump
Установим kdump с помощью команды
$ sudo apt-get install linux-crashdump kdump-tools
Настройки kdump хранятся в конфигурационном файле /etc/default/kdump-tools
# kdump-tools configuration # --------------------------------------------------------------------------- # USE_KDUMP - controls kdump will be configured # 0 - kdump kernel will not be loaded # 1 - kdump kernel will be loaded and kdump is configured # KDUMP_SYSCTL - controls when a panic occurs, using the sysctl # interface. The contents of this variable should be the # "variable=value ..." portion of the 'sysctl -w ' command. # If not set, the default value "kernel.panic_on_oops=1" will # be used. Disable this feature by setting KDUMP_SYSCTL=" " # Example - also panic on oom: # KDUMP_SYSCTL="kernel.panic_on_oops=1 vm.panic_on_oom=1" # USE_KDUMP=1 # KDUMP_SYSCTL="kernel.panic_on_oops=1"
Чтобы активировать kdump, отредактируем этот файл и установим значение параметра USE_KDUMP=1.
Также в конфигурационном файле содержатся следующие параметры:
- KDUMP_KERNEL — полный путь к аварийному ядру;
- KDUMP_INITRD — полный путь к initrd аварийного ядра;
- KDUMP_CORE — указывает, где будет сохранен файл дампа ядра. По умолчанию дамп сохраняется в директории /var/crash (KDUMP_CORE=/var/crash);
- KDUMP_FAIL_CMD — указывает, какое действие нужно совершить в случае ошибки при сохранении дампа (по умолчанию будет выполнена команда reboot -f);
- DEBUG_KERNEL — отладочная версия работающего ядра. По умолчанию используются /usr/lib/debug/vmlinux-$. Если значение этого параметра не установлено, утилита makedumpfile создаст только дамп всех страниц памяти;
- MAKEDUMP_ARGS — содержит дополнительные аргументы, передаваемые утилите makedumpfile. По умолчанию этот параметр имеет значение ‘-c -d 31’, указывающую, что необходимо использовать сжатие и включать в дамп только используемые страницы ядра.
Установив все необходимые параметры, выполним команду update-grub и выберем install the package maintainer’s version.
Затем перезагрузим систему и убедимся в том, что kdump готов к работе:
$ cat/proc/cmdline BOOT_IMAGE=/boot/vmlinuz-3.8.0-35-generic root=UUID=bb2ba5e1-48e1-4829-b565-611542b96018 ro crashkernel=384 -:128M quiet splash vt.handoff=7
Обратим особое внимание на параметр crashkernel=384 -:128M. Он означает, что аварийное ядро будет использовать 128 Мб памяти при загрузке. Можно прописать в grub параметр crashkernel = auto: в этом случае память под аварийное ядро будет выделяться автоматически.
Для того, чтобы мы могли анализировать дамп с помощью утилиты crash, нам понадобится также файл vmlinux, содержащий отладочную информацию:
$ sudo tee /etc/apt/sources.list.d/ddebs.list << EOF deb http://ddebs.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse deb http://ddebs.ubuntu.com/ $(lsb_release -cs)-security main restricted universe multiverse deb http://ddebs.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse deb http://ddebs.ubuntu.com/ $(lsb_release -cs)-proposed main restricted universe multiverse EOF $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01 $ sudo apt-get update $ sudo apt-get install linux-image-$(uname -r)-dbgsym
По завершении установки еще раз проверим статус kdump:
$ kdump-config status
Если kdump находится в рабочем состоянии, на консоль будет выведено следующее сообщение:
current state: ready to kdump
Тестируем kdump
Вызовем панику ядра при помощи следующих команд:
echo c | sudo tee /proc/sysrq-trigger
В результате их выполнения система «зависнет».
После этого в течение нескольких минут будет создан дамп, который будет доступен в директории /var/crash после перезагрузки.
Информацию о сбое ядра можно просмотреть с помощью утилиты crash:
$ sudo crash /usr/lib/debug/boot/vmlinux-3.13.0-24-generic /var/crash/201405051934/dump.201405051934 crash 7.0.3 Copyright (C) 2002-2013 Red Hat, Inc. Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation Copyright (C) 1999-2006 Hewlett-Packard Co Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited Copyright (C) 2006, 2007 VA Linux Systems Japan K.K. Copyright (C) 2005, 2011 NEC Corporation Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc. Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. This program is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Enter "help copying" to see the conditions. This program has absolutely no warranty. Enter "help warranty" for details. GNU gdb (GDB) 7.6 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu"... KERNEL: /usr/lib/debug/boot/vmlinux-3.13.0-24-generic DUMPFILE: /var/crash/201405051934/dump.201405051934 [PARTIAL DUMP] CPUS: 4 DATE: Mon May 5 19:34:38 2014 UPTIME: 00:54:46 LOAD AVERAGE: 0.14, 0.07, 0.05 TASKS: 495 NODENAME: Ubuntu RELEASE: 3.13.0-24-generic VERSION: #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 MACHINE: x86_64 (2675 Mhz) MEMORY: 8 GB PANIC: "Oops: 0002 [#1] SMP " (check log for details) PID: 7826 COMMAND: "tee" TASK: ffff8800a2ef8000 [THREAD_INFO: ffff8800a2e68000] CPU: 2 STATE: TASK_RUNNING (PANIC) crash>
На основе приведенного вывода мы можем заключить, что системному сбою предшествовало событие «Oops: 0002 [#1] SMP», произошедшее на CPU2 при выполнении команды tee.
Утилита crash обладает также широким спектром возможностей для диагностики причин краха ядра. Рассмотрим их более подробно.
Диагностика причин сбоя с помощью утилиты crash
Crash сохраняет информацию обо всех системных событиях, предшествовавших краху ядра. С ее помощью можно воссоздать состояние системы на момент сбоя: узнать, какие процессы были запущены на момент краха, какие файлы открыты и т.п. Эта информация помогает поставить точный диагноз и предупредить крахи ядра в будущем.
В утилите crash имеется свой набор команд:
$ crash> help * files mach repeat timer alias foreach mod runq tree ascii fuser mount search union bt gdb net set vm btop help p sig vtop dev ipcs ps struct waitq dis irq pte swap whatis eval kmem ptob sym wr exit list ptov sys q extend log rd task crash version: 7.0.3 gdb version: 7.6 For help on any command above, enter "help <command>". For help on input options, enter "help input". For help on output options, enter "help output". crash>
Для каждой этой команды можно вызвать краткий мануал, например:
crash> help set
Все команды мы описывать не будем (с детальной информацией можно ознакомиться в официальном руководстве пользователя от компании RedHat), а расскажем лишь о наиболее важных из них.
В первую очередь следует обратить внимание на команду bt (аббревиатура от backtrace — обратная трассировка). С ее помощью можно посмотреть детальную информацию о содержании памяти ядра (подробности и примеры использования см. здесь). Однако во многих случаях для определения причины системного сбоя бывает вполне достаточно команды log, выводящее на экран содержимое буфера сообщений ядра в хронологическом порядке.
Приведем фрагмент ее вывода:
[ 3288.251955] CPU: 2 PID: 7826 Comm: tee Tainted: PF O 3.13.0-24-generic #46-Ubuntu [ 3288.251957] Hardware name: System manufacturer System Product Name/P7P55D LE, BIOS 2003 12/16/2010 [ 3288.251958] task: ffff8800a2ef8000 ti: ffff8800a2e68000 task.ti: ffff8800a2e68000 [ 3288.251960] RIP: 0010:[<ffffffff8144de76>] [<ffffffff8144de76>] sysrq_handle_crash+0x16/0x20 [ 3288.251963] RSP: 0018:ffff8800a2e69e88 EFLAGS: 00010082 [ 3288.251964] RAX: 000000000000000f RBX: ffffffff81c9f6a0 RCX: 0000000000000000 [ 3288.251965] RDX: ffff88021fc4ffe0 RSI: ffff88021fc4e3c8 RDI: 0000000000000063 [ 3288.251966] RBP: ffff8800a2e69e88 R08: 0000000000000096 R09: 0000000000000387 [ 3288.251968] R10: 0000000000000386 R11: 0000000000000003 R12: 0000000000000063 [ 3288.251969] R13: 0000000000000246 R14: 0000000000000004 R15: 0000000000000000 [ 3288.251971] FS: 00007fb0f665b740(0000) GS:ffff88021fc40000(0000) knlGS:0000000000000000 [ 3288.251972] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 3288.251973] CR2: 0000000000000000 CR3: 00000000368fd000 CR4: 00000000000007e0 [ 3288.251974] Stack: [ 3288.251975] ffff8800a2e69ec0 ffffffff8144e5f2 0000000000000002 00007fff3cea3850 [ 3288.251978] ffff8800a2e69f50 0000000000000002 0000000000000008 ffff8800a2e69ed8 [ 3288.251980] ffffffff8144eaff ffff88021017a900 ffff8800a2e69ef8 ffffffff8121f52d [ 3288.251983] Call Trace: [ 3288.251986] [<ffffffff8144e5f2>] __handle_sysrq+0xa2/0x170 [ 3288.251988] [<ffffffff8144eaff>] write_sysrq_trigger+0x2f/0x40 [ 3288.251992] [<ffffffff8121f52d>] proc_reg_write+0x3d/0x80 [ 3288.251996] [<ffffffff811b9534>] vfs_write+0xb4/0x1f0 [ 3288.251998] [<ffffffff811b9f69>] SyS_write+0x49/0xa0 [ 3288.252001] [<ffffffff8172663f>] tracesys+0xe1/0xe6 [ 3288.252002] Code: 65 34 75 e5 4c 89 ef e8 f9 f7 ff ff eb db 0f 1f 80 00 00 00 00 66 66 66 66 90 55 c7 05 94 68 a6 00 01 00 00 00 48 89 e5 0f ae f8 <c6> 04 25 00 00 00 00 01 5d c3 66 66 66 66 90 55 31 c0 c7 05 be [ 3288.252025] RIP [<ffffffff8144de76>] sysrq_handle_crash+0x16/0x20 [ 3288.252028] RSP <ffff8800a2e69e88> [ 3288.252029] CR2: 0000000000000000
В одной из строк вывода будет указано событие, вызвавшее системную ошибку:
[ 3288.251889] SysRq: Trigger a crash
С помощью команды ps можно вывести на экран список процессов, которые были запущены на момент сбоя:
crash> ps PID PPID CPU TASK ST %MEM VSZ RSS COMM 0 0 0 ffffffff81a8d020 RU 0.0 0 0 [swapper] 1 0 0 ffff88013e7db500 IN 0.0 19356 1544 init 2 0 0 ffff88013e7daaa0 IN 0.0 0 0 [kthreadd] 3 2 0 ffff88013e7da040 IN 0.0 0 0 [migration/0] 4 2 0 ffff88013e7e9540 IN 0.0 0 0 [ksoftirqd/0] 7 2 0 ffff88013dc19500 IN 0.0 0 0 [events/0]
Для просмотра информации об использовании виртуальной памяти используется команда vm:
crash> vm PID: 5210 TASK: ffff8801396f6aa0 CPU: 0 COMMAND: "bash" MM PGD RSS TOTAL_VM ffff88013975d880 ffff88013a0c5000 1808k 108340k VMA START END FLAGS FILE ffff88013a0c4ed0 400000 4d4000 8001875 /bin/bash ffff88013cd63210 3804800000 3804820000 8000875 /lib64/ld-2.12.so ffff880138cf8ed0 3804c00000 3804c02000 8000075 /lib64/libdl-2.12.so
Команда swap выведет на консоль информацию об использовании области подкачки:
crash> swap FILENAME TYPE SIZE USED PCT PRIORITY /dm-1 PARTITION 2064376k 0k 0% -1
Информацию о прерываниях CPU можно просмотреть с помощью команды irq:
crash> irq -s CPU0 0: 149 IO-APIC-edge timer 1: 453 IO-APIC-edge i8042 7: 0 IO-APIC-edge parport0 8: 0 IO-APIC-edge rtc0 9: 0 IO-APIC-fasteoi acpi 12: 111 IO-APIC-edge i8042 14: 108 IO-APIC-edge ata_piix
Вывести на консоль список файлов, открытых на момент сбоя, можно с помощью команды files:
crash> files PID: 5210 TASK: ffff8801396f6aa0 CPU: 0 COMMAND: "bash" ROOT: / CWD: /root FD FILE DENTRY INODE TYPE PATH 0 ffff88013cf76d40 ffff88013a836480 ffff880139b70d48 CHR /tty1 1 ffff88013c4a5d80 ffff88013c90a440 ffff880135992308 REG /proc/sysrq-trigger 255 ffff88013cf76d40 ffff88013a836480 ffff880139b70d48 CHR /tty1
Наконец, получить в сжатом виде информацию об общем состоянии системы можно с помощью команды sys:
crash> sys KERNEL: /usr/lib/debug/lib/modules/2.6.32-431.5.1.el6.x86_64/vmlinux DUMPFILE: /var/crash/127.0.0.1-2014-03-26-12:24:39/vmcore [PARTIAL DUMP] CPUS: 1 DATE: Wed Mar 26 12:24:36 2014 UPTIME: 00:01:32 LOAD AVERAGE: 0.17, 0.09, 0.03 TASKS: 159 NODENAME: elserver1.abc.com RELEASE: 2.6.32-431.5.1.el6.x86_64 VERSION: #1 SMP Fri Jan 10 14:46:43 EST 2014 MACHINE: x86_64 (2132 Mhz) MEMORY: 4 GB PANIC: "Oops: 0002 [#1] SMP " (check log for details)
Заключение
Анализ и диагностика причин падения ядра представляет собой очень специфическую и сложную тему, которую невозможно уместить в рамки одной статьи. Мы еще вернемся к ней в следующих публикациях.
Для желающих узнать больше — несколько полезных ссылок:
- Документация kdump на сайте kernel.org
- Книга, целиком посвященная проблемам диагностики сбоев ядра
- Подробная документация для утилиты crash
Читателей, которые не могут оставлять комментарии здесь, приглашаем к нам в блог.
Автор: yuhenobi