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

发布于 2024-08-29 19:46:50 字数 235 浏览 7 评论 0原文

有没有办法为特定进程配置核心转储文件的放置目录?

我有一个用 C++ 编写的守护进程,我想为其配置核心转储目录。 (可选)文件名模式也应该是可配置的。

我知道/proc/sys/kernel/core_pattern,但是这会改变全局的模式和目录结构。

Apache 有指令 CoreDumpDirectory - 所以这似乎是可能的。

Is there a way to configure the directory where core dump files are placed for a specific process?

I have a daemon process written in C++ for which I would like to configure the core dump directory. Optionally the filename pattern should be configurable, too.

I know about /proc/sys/kernel/core_pattern, however this would change the pattern and directory structure globally.

Apache has the directive CoreDumpDirectory - so it seems to be possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

硬不硬你别怂 2024-09-05 19:46:50

不,您不能为每个进程设置它。核心文件被转储到进程的当前工作目录,或者如果模式包含目录,则转储到 /proc/sys/kernel/core_pattern 中设置的目录。

apache 中的 CoreDumpDirectory 是一个 hack,apache 为所有导致 core dump 的信号注册信号处理程序,并更改其信号处理程序中的当前目录。

/* 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.
     */
}

No, you cannot set it per process. The core file gets dumped either to the current working directory of the process, or the directory set in /proc/sys/kernel/core_pattern if the pattern includes a directory.

CoreDumpDirectory in apache is a hack, apache registers signal handlers for all signals that cause a core dump , and changes the current directory in its signal handler.

/* 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.
     */
}
霞映澄塘 2024-09-05 19:46:50

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

%% 单个 % 字符
%c 崩溃进程的核心文件大小软资源限制
%d 转储模式 — 与 prctl(2) PR_GET_DUMPABLE 返回的值相同
%e 可执行文件名(不带路径前缀)
%E 可执行文件的路径名,斜杠('/')替换为感叹号('!')
%g(数字)转储进程的真实 GID
%h 主机名(与 uname(2) 返回的节点名相同)
%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
$

创建一个崩溃的示例程序(例如失败.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 重定向核心转储:

$ 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

It is possible to make it using the "|command" mechanism of the core_pattern file. The executed command can create the directories and files as needed. The command can be passed the following specifiers in the parameters (cf. man 5 core):

%% a single % character
%c core file size soft resource limit of crashing process
%d dump mode—same as value returned by prctl(2) PR_GET_DUMPABLE
%e executable filename (without path prefix)
%E pathname of executable, with slashes ('/') replaced by exclamation marks ('!')
%g (numeric) real GID of dumped process
%h hostname (same as nodename returned by uname(2))
%i TID of thread that triggered core dump, as seen in the PID namespace in which the thread resides
%I TID of thread that triggered core dump, as seen in the initial PID namespace
%p PID of dumped process, as seen in the PID namespace in which the process resides
%P PID of dumped process, as seen in the initial PID namespace
%s number of signal causing dump
%t time of dump, expressed as seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)
%u (numeric) real UID of dumped process

For example, it is possible to create a script (e.g. named crash.sh) as follow:

#!/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

In the 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
$

Create an example program which crashes (e.g. fail.c):

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

  *ptr = 'q';

  return 0;

}

Compile the program (make several executables) and adjust the core file size in the current shell:

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

Run the failing programs several times to have multiple processes ids:

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

Look at /tmp where the core_pattern redirects the core dumps:

$ 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文