gpt4 book ai didi

c - 向stderr写入数据使程序成为守护进程后退出

转载 作者:太空狗 更新时间:2023-10-29 11:22:17 25 4
gpt4 key购买 nike

请看这段代码。它运行在 CentOS6 64 位。

#include<stdio.h>

int main(int argc, char **argv)
{
fprintf(stderr, "output 1\n");
printf("output 2\n");
fflush(stdout);
system("echo abc");
fprintf(stderr, "output 3\n ");
printf("output 4\n");
fflush(stdout);

daemon(0, 1);

fprintf(stderr, "output 5\n");
printf("output 6\n");
fflush(stdout);
system("echo abc");
fprintf(stderr, "output 7\n");
printf("output 8\n");
fflush(stdout);

}

如果我运行它,我会看到这些消息:

output 1
output 2
abc
output 3
output 4
output 5
output 6
abc
output 7
output 8

如果我使用 ssh 登录并运行它,我会看到相同的结果。

但是,如果我使用二进制名称作为ssh 的参数并运行它,程序将在调用daemon(0, 1) 后向stderr 写入数据时退出。假设二进制名称是 myapp。我跑

ssh localhost myapp

我只会看到这些消息:

output 1
output 2
abc
output 3
output 4
output 5
output 6
abc

有人知道为什么吗?根据调试,程序只做了三件事就退出了:

  1. 调用守护进程 (0, 1)。
  2. 调用系统运行另一个应用程序或 bash 命令。
  3. 写一些东西到 stderr。

非常感谢!

最佳答案

如果您从 shell 运行此命令,您可能会在输出 4 和输出 5 之间看到一个新的 shell 提示(如果输出行之间有休眠,这会更加明显)。

那是因为daemon()系统调用导致程序 split 成两个独立的进程。这称为“fork”,可以使用 fork() 系统调用更紧密地控制它。在 fork 之后,两个进程都保留指向打开文件描述符的指针:stdin、stdout 和 stderr。根据“man 3 daemon”,父进程在fork之后调用exit()

当您从 SSH 调用可执行文件时,SSH session 将运行一个进程。它 fork 出一个 child ,然后主进程退出。 SSH 看到您发出的命令已经完成,因此它关闭了 SSH 连接。这将关闭 stdout 和 stderr。不幸的是,您的子进程仍有一些工作要做,但它无法写入共享标准错误,因为该文件描述符已关闭。如果您打印更多调试信息,例如 printf()fprintf() 调用的返回值,您会发现它无法写入关闭的文件描述符。

如果您不打印到 stderr,而是打印到日志文件(大多数守护进程都这样做),那么您会看到子进程将继续在后台运行并按照您的预期进行写入。

如果您选择使用 fork() 而不是 daemon(),您可以让父进程等待子进程完成。您可以使用 pid_t waitpid(pid_t pid, int *stat_loc, int options);

您可能还想查看父子之间发送的信号。当一个子进程死亡时,它会发送 SIGCHILD 给父进程。如果您想要反向通知,您可以使用 prctl(PR_SET_PDEATHSIG, SIGHUP); 设置一个(仅在 Linux 上),以便 parent 向 child 发送一个 SIGHUP。

关于c - 向stderr写入数据使程序成为守护进程后退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22295279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com