У меня есть процесс в Linux, который получает ошибку сегментации. Как я могу сказать ему, чтобы генерировать дамп ядра при сбое?
У меня есть процесс в Linux, который получает ошибку сегментации. Как я могу сказать ему, чтобы генерировать дамп ядра при сбое?
Ответы:
Это зависит от того, какую оболочку вы используете. Если вы используете bash, то команда ulimit контролирует несколько параметров, связанных с выполнением программы, например, следует ли вам выгружать ядро. Если вы печатаете
ulimit -c unlimited
тогда это скажет bash, что его программы могут выгружать ядра любого размера. Вы можете указать размер, например, 52 МБ, а не неограниченный, если хотите, но на практике это не требуется, поскольку размер основных файлов, вероятно, никогда не будет проблемой для вас.
В tcsh вы наберете
limit coredumpsize unlimited
Как объяснялось выше, реальный вопрос, который здесь задают, заключается в том, как включить дампы ядра в системе, где они не включены. На этот вопрос ответ здесь.
Если вы пришли сюда в надежде узнать, как создать дамп ядра для зависшего процесса, ответ:
gcore <pid>
если gcore недоступен в вашей системе, то
kill -ABRT <pid>
Не используйте kill -SEGV, так как это часто вызывает обработчик сигнала, затрудняя диагностику зависшего процесса.
-ABRT
вызовет обработчик сигнала, чем -SEGV
, поскольку прерывание с большей вероятностью будет восстановимо, чем сегфоут. (Если вы обрабатываете segfault, обычно он просто срабатывает снова, как только ваш обработчик завершает работу.) Лучший выбор сигнала для генерации дампа ядра - это -QUIT
.
Чтобы проверить, где генерируются дампы ядра, запустите:
sysctl kernel.core_pattern
или:
cat /proc/sys/kernel/core_pattern
где %e
имя процесса и %t
системное время. Вы можете изменить его /etc/sysctl.conf
и перезагрузить sysctl -p
.
Если основные файлы не создаются (протестируйте его: sleep 10 &
а killall -SIGSEGV sleep
) проверьте ограничения по: ulimit -a
.
Если размер вашего основного файла ограничен, запустите:
ulimit -c unlimited
сделать это неограниченным.
Затем проверьте снова, если дамп ядра успешен, вы увидите «(дамп ядра)» после индикации ошибки сегментации, как показано ниже:
Ошибка сегментации: 11 (ядро сброшено)
Смотрите также: ядро сброшено - но файл ядра не находится в текущем каталоге?
В Ubuntu дампы ядра обрабатываются Apport и могут быть расположены в /var/crash/
. Однако он по умолчанию отключен в стабильных выпусках.
Для более подробной информации, пожалуйста, проверьте: Где я могу найти дамп ядра в Ubuntu? ,
Для macOS см .: Как создать дамп ядра в Mac OS X?
В конце я подключил gdb к процессу до его сбоя, а затем, когда он получил segfault, я выполнил generate-core-file
команду. Это заставило генерацию основной памяти.
ge
)
ulimit -c
на unlimited
, но файл ядра успокоен не создан, generate-core-file
файл в GdB сессии действительно создает файл ядра, спасибо.
Может быть, вы могли бы сделать это таким образом, эта программа демонстрирует, как перехватить ошибку сегментации, и отправляет ее отладчику (это исходный код, используемый ниже AIX
) и печатает трассировку стека до точки ошибки сегментации. Вам нужно будет изменить sprintf
переменную для использования gdb
в случае Linux.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);
struct sigaction sigact;
char *progname;
int main(int argc, char **argv) {
char *s;
progname = *(argv);
atexit(cleanup);
init_signals();
printf("About to seg fault by assigning zero to *s\n");
*s = 0;
sigemptyset(&sigact.sa_mask);
return 0;
}
void init_signals(void) {
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGSEGV);
sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGBUS);
sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGQUIT);
sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGHUP);
sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);
sigaddset(&sigact.sa_mask, SIGKILL);
sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}
static void signal_handler(int sig) {
if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
if (sig == SIGSEGV || sig == SIGBUS){
dumpstack();
panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
}
if (sig == SIGQUIT) panic("QUIT signal ended program\n");
if (sig == SIGKILL) panic("KILL signal ended program\n");
if (sig == SIGINT) ;
}
void panic(const char *fmt, ...) {
char buf[50];
va_list argptr;
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
va_end(argptr);
fprintf(stderr, buf);
exit(-1);
}
static void dumpstack(void) {
/* Got this routine from http://www.whitefang.com/unix/faq_toc.html
** Section 6.5. Modified to redirect to file to prevent clutter
*/
/* This needs to be changed... */
char dbx[160];
sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
/* Change the dbx to gdb */
system(dbx);
return;
}
void cleanup(void) {
sigemptyset(&sigact.sa_mask);
/* Do any cleaning up chores here */
}
Вы , возможно , придется дополнительно добавить параметр , чтобы получить GDB сбросить ядро , как показано здесь , в этом блоге здесь .
Есть еще вещи, которые могут повлиять на генерацию дампа ядра. Я столкнулся с этим:
/proc/sys/kernel/core_pattern
. /proc/sys/fs/suid_dumpable
может препятствовать генерации ядра.Есть еще ситуации, которые могут помешать генерации, которые описаны на странице руководства - попробуйте man core
.
Чтобы активировать дамп ядра, сделайте следующее:
В /etc/profile
комментарии строка:
# ulimit -S -c 0 > /dev/null 2>&1
В /etc/security/limits.conf
комментируем строчку:
* soft core 0
выполнить cmd limit coredumpsize unlimited
и проверить его с помощью cmd limit
:
# limit coredumpsize unlimited
# limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize 10240 kbytes
coredumpsize unlimited
memoryuse unlimited
vmemoryuse unlimited
descriptors 1024
memorylocked 32 kbytes
maxproc 528383
#
чтобы проверить, записан ли corefile, вы можете уничтожить связанный процесс с помощью cmd kill -s SEGV <PID>
(не нужно, на всякий случай, если не записан ни один файл core, это можно использовать как проверку):
# kill -s SEGV <PID>
После того, как файл core записан, убедитесь, что снова отключили настройки coredump в соответствующих файлах (1./2./3.)!
Для Ubuntu 14.04
Проверьте дамп ядра включен:
ulimit -a
Одна из строк должна быть:
core file size (blocks, -c) unlimited
Если не :
gedit ~/.bashrc
и добавить ulimit -c unlimited
в конец файла и сохранить, перезапустить терминал.
Создайте свое приложение с отладочной информацией:
В Makefile -O0 -g
Запустите приложение, которое создает дамп ядра (файл дампов ядра с именем 'core' должен быть создан рядом с файлом application_name):
./application_name
Запустите под GDB:
gdb application_name core
ulimit -c unlimited
терминал для временного решения, потому что только редактирование ~/.bashrc
требует перезапуска терминала, чтобы изменения вступили в силу.
По умолчанию вы получите основной файл. Убедитесь, что текущий каталог процесса доступен для записи, иначе файл ядра не будет создан.
Лучше включить программный дамп ядра с помощью системного вызова setrlimit
.
пример:
#include <sys/resource.h>
bool enable_core_dump(){
struct rlimit corelim;
corelim.rlim_cur = RLIM_INFINITY;
corelim.rlim_max = RLIM_INFINITY;
return (0 == setrlimit(RLIMIT_CORE, &corelim));
}
ulimit -c unlimited
в командной строке среды, а затем перезапустите приложение.
ulimit -c unlimited
. Также вы можете скомпилировать с определением marco, приложение не будет включать enable_core_dump
символ, если не определит этот макрос при выпуске, и вы получите дамп ядра, замененный отладочной версией.
Стоит отметить, что если у вас настроен systemd , то все немного по-другому. Обычно в настройках файлы ядра core_pattern
передаются через значение sysctl через systemd-coredump(8)
. Размер основного файла rlimit обычно уже настроен как «неограниченный».
Затем можно извлечь дампы ядра, используя coredumpctl(1)
.
Хранение дампов ядра и т. Д. Настраивается с помощью coredump.conf(5)
. Есть примеры того, как получить файлы ядра на странице руководства coredumpctl, но вкратце это будет выглядеть так:
Найдите основной файл:
[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET 16163 1224 1224 11 present /home/vps/test_me
Получить основной файл:
[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163
Ubuntu 19.04
Все остальные ответы не помогли мне. Но следующая сумма сделала работу
Создайте ~/.config/apport/settings
со следующим содержанием:
[main]
unpackaged=true
(Это говорит apport также писать дампы ядра для пользовательских приложений)
проверить: ulimit -c
. Если он выдает 0, исправьте это с помощью
ulimit -c unlimited
На всякий случай перезапустите apport:
sudo systemctl restart apport
Файлы Crash теперь записаны в /var/crash/
. Но вы не можете использовать их с GDB. Чтобы использовать их с GDB, используйте
apport-unpack <location_of_report> <target_directory>
Дальнейшая информация:
core_pattern
. Помните, что этот файл может быть перезаписан сервисом apport при перезапуске.ulimit -c
Значение может переодеться автоматически в то время как вы пытаетесь другие ответы в Интернете. Обязательно проверяйте его регулярно во время настройки создания дампа ядра.Ссылки: