【问题标题】:Is changing parent process necessary when daemonize a process?守护进程时是否需要更改父进程?
【发布时间】:2016-06-12 20:10:08
【问题描述】:

我在https://en.wikipedia.org/wiki/Daemon_%28computing%29#Creation阅读有关守护进程的信息

在严格的技术意义上,类 Unix 系统进程是一个守护进程 当它的父进程终止并且守护进程被分配了init 进程(进程号 1)作为其父进程,并且没有 控制终端。然而,更常见的是,守护进程可以是任何 后台进程,无论是否是 init 进程的子进程。

在类 Unix 系统上,将进程变为 守护进程,当进程从命令行或从 启动脚本,例如 init 脚本或 SystemStarter 脚本, 涉及:

  1. 与控制终端分离
  2. 成为会议负责人
  3. 成为流程组组长
  4. 通过分叉和退出(一次或两次)作为后台任务执行。有时需要该过程才能成为会话 领导。它还允许父进程继续正常 执行。
  5. 将根目录 (/) 设置为当前工作目录,这样进程就不会保留任何可能正在使用的目录 已挂载的文件系统(允许卸载)。
  6. 将 umask 更改为 0 以允许 open()、creat() 和其他操作系统调用提供自己的权限掩码,而不是 依赖于调用者的umask
  7. 在执行时关闭所有被父进程打开的继承文件,包括文件描述符 0、1 和 2 对于标准流(stdin、stdout 和 stderr)。所需文件 稍后会开放。
  8. 使用日志文件、控制台或 /dev/null 作为标准输入、标准输出和标准错误

如果进程由超级服务器守护进程启动,例如 inetd, launchd 或 systemd,超级服务器守护进程将执行这些 进程 [5][6][7] 的函数(旧式守护进程除外 转换为在 systemd 下运行并指定为 Type=forking[7] 和 inetd[5] 下的“多线程”数据报服务器)。

  1. 那里有一个步骤可以改变一个进程的父进程 被守护?在我看来,没有一个步骤可以做到这一点?

    在守护进程时是否需要更改父进程?

  2. 改变一个进程的父进程后(一个进程不一定 被守护),该进程是否可以关联到控制 新父进程的tty? (这个问题的目的是 查看是否“保持进程与 控制新父进程的tty”是必要条件 “改变进程的父进程”。)

查看我的相关问题https://unix.stackexchange.com/questions/266565/daemonize-a-process-in-shell

谢谢。

【问题讨论】:

标签: linux daemon


【解决方案1】:

Unix 进程的父进程不能由进程本身更改。创建守护进程的典型方法涉及fork 调用(它创建将成为守护进程的进程)。然后初始进程退出,新孤立的子进程将被init 进程继承,成为它的新父进程。这在第 4 步中处理。init 唯一要做的就是等待它的所有孩子退出。 init 没有控制 TTY,因此一旦被 init 继承,守护程序就不能再与控制 TTY 关联。解除关联的主要原因是防止 TTY 生成的信号(挂断和控制 C 等)到达守护程序。

守护进程通常有两种运行方式:

  1. 来自 shell 脚本。该脚本在命令末尾使用& 运算符运行守护程序的可执行文件以将守护程序置于后台,可能使用 I/O 重定向来设置守护程序的标准输入、标准输出和/或标准错误,然后退出离开守护程序没有父母。从 shell 运行可执行文件涉及 shell 在要运行的可执行文件的子进程中执行 fork 后跟 exec

  2. 守护程序有一个自行守护程序的选项。当使用该选项运行时,它会在子进程中执行fork,然后是带有适当参数集的自身exec。父母通常会在fork 之后退出,因为它被要求做的工作已经完成。如果没有,子进程需要一个额外的fork 给它一个可以退出的父进程。注意:这就是为什么这么多通常作为守护进程运行的程序可以直接运行而不成为守护进程的原因,“成为守护进程”选项会导致子进程关闭 stdin/stdout/stderr 然后只是exec它自己的可执行文件没有“成为守护进程”选项。

【讨论】:

  • 谢谢。在运行守护进程的第一种方式中,“脚本在命令末尾使用 & 运算符运行守护进程的可执行文件以将守护进程置于后台”是否允许父进程“然后在没有父进程的情况下退出守护进程”?如果我是正确的,后台进程不足以允许其父进程退出而自身不退出。我们需要 disown 或 nohup 进程,除了后台处理它,这样当它的父进程退出时,它就不会退出。
  • 我从来没有发现 SIGHUP 会传播给子进程,可能是因为& 将子进程放在它自己的进程组中,因此发送给父进程的信号不会传递给子进程。如果父母有一个 TTY 作为标准输入,孩子的标准输入没有被重定向并且孩子没有足够快地关闭标准输入,如果父母退出并导致 TTY 被破坏,孩子可能会从 TTY 收到 SIGHUP。将孩子的标准输入重定向到 /dev/null 如此自动,我不记得上次遇到这个问题是什么时候了,但它可能会发生。
【解决方案2】:

我建议使用daemon(3)。另见credentials(7)

您的列表没有明确提及setsid(2)

MUSL libc 有一个 legacy/daemon.c 分叉两次并执行 setsid

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-02
    • 2015-08-23
    • 1970-01-01
    相关资源
    最近更新 更多