linux 每个进程可配置的核心转储目录

nafvub8i  于 2023-08-03  发布在  Linux
关注(0)|答案(2)|浏览(129)

有没有办法为特定进程配置核心转储文件所在的目录?
我有一个用C++编写的守护进程,我想为它配置核心转储目录。文件名模式也应该是可配置的。
我知道/proc/sys/kernel/core_pattern,但是这会改变模式和目录结构 * 全局 *。
Apache有指令CoreDumpDirectory-所以这似乎是可能的。

3phpmpom

3phpmpom1#

不可以,您不能按进程设置。核心文件被转储到进程的当前工作目录,或者如果模式包含目录,则转储到/proc/sys/kernel/core_pattern中设置的目录。
Apache中的CoreDumpDirectory是一个黑客,Apache为所有导致核心转储的信号注册信号处理程序,并在其信号处理程序中更改当前目录。

/* handle all varieties of core dumping signals */
static void sig_coredump(int sig)
{
    apr_filepath_set(ap_coredump_dir, pconf);
    apr_signal(sig, SIG_DFL);
#if AP_ENABLE_EXCEPTION_HOOK
    run_fatal_exception_hook(sig);
#endif
    /* linuxthreads issue calling getpid() here:
     *   This comparison won't match if the crashing thread is
     *   some module's thread that runs in the parent process.
     *   The fallout, which is limited to linuxthreads:
     *   The special log message won't be written when such a
     *   thread in the parent causes the parent to crash.
     */
    if (getpid() == parent_pid) {
        ap_log_error(APLOG_MARK, APLOG_NOTICE,
                     0, ap_server_conf,
                     "seg fault or similar nasty error detected "
                     "in the parent process");
        /* XXX we can probably add some rudimentary cleanup code here,
         * like getting rid of the pid file.  If any additional bad stuff
         * happens, we are protected from recursive errors taking down the
         * system since this function is no longer the signal handler   GLA
         */
    }
    kill(getpid(), sig);
    /* At this point we've got sig blocked, because we're still inside
     * the signal handler.  When we leave the signal handler it will
     * be unblocked, and we'll take the signal... and coredump or whatever
     * is appropriate for this particular Unix.  In addition the parent
     * will see the real signal we received -- whereas if we called
     * abort() here, the parent would only see SIGABRT.
     */
}

字符串

u1ehiz5o

u1ehiz5o2#

可以使用“|命令”机制的core_pattern文件。执行的命令可以根据需要创建目录和文件。命令可以在参数中传递以下说明符(参见man 5 core):

**%%**单个%字符
%c崩溃进程的核心文件大小软资源限制
%d转储模式-与prctl(2)PR_GET_DUMPABLE返回的值相同
%e可执行文件名(无路径前缀)
%E可执行文件的路径名,斜杠('/')替换为感叹号('!')
%g(数值)转储进程的真实的GID
%hhostname(与uname(2)返回的nodename相同)
%i触发核心转储的线程的TID,如线程所在的PID命名空间所示
%I触发核心转储的线程的TID,如初始PID命名空间中所示
%p转储进程的PID,如进程所在的PID命名空间所示
%P转储进程的PID,如初始PID命名空间所示
%s导致转储的信号数
%t转储时间,表示为自纪元以来的秒数,1970-01-01 00:00:00 +0000(UTC)
%u(数值)转储进程的真实的UID

例如,可以创建脚本(例如,crash.sh)如下:

#!/bin/bash

# $1: process number on host side (%P)
# $2: program's name (%e)

OUTDIR=/tmp/core/$2
OUTFILE="core_$1"

# Create a sub-directory in /tmp
mkdir -p "$OUTDIR"

# Redirect stdin in a per-process file:
cat > "$OUTDIR"/"$OUTFILE"

exit 0

字符串
在shell中:

$ chmod +x crash.sh
$ mv crash.sh /tmp  # Put the script in some place
$ sudo su
# echo '|/tmp/crash.sh %P %e' > /proc/sys/kernel/core_pattern
# cat /proc/sys/kernel/core_pattern
|/tmp/crash.sh %P %e
# exit
$


创建一个崩溃的示例程序(例如fail.c):

int main(void)
{
  char *ptr = (char *)0;

  *ptr = 'q';

  return 0;

}


编译程序(生成几个可执行文件)并调整当前shell中的核心文件大小:

$ gcc fail.c -o fail1
$ gcc fail.c -o fail2
$ ulimit -c
0
$ ulimit -c unlimited
$ ulimit -c
unlimited


运行失败的程序几次以获得多个进程id:

$ ./fail1
Segmentation fault (core dumped)
$ ./fail2
Segmentation fault (core dumped)
$ ./fail1
Segmentation fault (core dumped)
$ ./fail2
Segmentation fault (core dumped)


看看/tmp,core_pattern重定向了core转储:

$ ls -l /tmp/core
total 8
drwxrwxrwx 2 root root 4096 nov.    3 15:57 fail1
drwxrwxrwx 2 root root 4096 nov.    3 15:57 fail2
$ ls -l /tmp/core/fail1/
total 480
-rw-rw-rw- 1 root root 245760 nov.    3 15:57 core_10606
-rw-rw-rw- 1 root root 245760 nov.    3 15:57 core_10614
$ ls -l /tmp/core/fail2 
total 480
-rw-rw-rw- 1 root root 245760 nov.    3 15:57 core_10610
-rw-rw-rw- 1 root root 245760 nov.    3 15:57 core_10618

相关问题