从systemd启动主进程时无法分离子进程 [英] Can't detach child process when main process is started from systemd

查看:45
本文介绍了从systemd启动主进程时无法分离子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想生成长时间运行的子进程,这些子进程在主进程重新启动/死亡时仍然存在.从终端运行时,这可以正常工作:

I want to spawn long-running child processes that survive when the main process restarts/dies. This works fine when running from the terminal:

$ cat exectest.go
package main

import (
        "log"
        "os"
        "os/exec"
        "syscall"
        "time"
)

func main() {
        if len(os.Args) == 2 && os.Args[1] == "child" {
                for {   
                        time.Sleep(time.Second)
                }
        } else {
                cmd := exec.Command(os.Args[0], "child")
                cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
                log.Printf("child exited: %v", cmd.Run())
        }
}
$ go build
$ ./exectest
^Z
[1]+  Stopped                 ./exectest
$ bg
[1]+ ./exectest &
$ ps -ef | grep exectest | grep -v grep | grep -v vim
snowm     7914  5650  0 23:44 pts/7    00:00:00 ./exectest
snowm     7916  7914  0 23:44 ?        00:00:00 ./exectest child
$ kill -INT 7914 # kill parent process
[1]+  Exit 2                  ./exectest
$ ps -ef | grep exectest | grep -v grep | grep -v vim
snowm     7916     1  0 23:44 ?        00:00:00 ./exectest child

注意,父进程被杀死后,子进程还活着.但是,如果我像这样从 systemd 启动主进程...

Note that the child process is still alive after parent process was killed. However, if I start the main process from systemd like this...

[snowm@localhost exectest]$ cat /etc/systemd/system/exectest.service 
[Unit]
Description=ExecTest

[Service]                        
Type=simple
ExecStart=/home/snowm/src/exectest/exectest
User=snowm

[Install]
WantedBy=multi-user.target
$ sudo systemctl enable exectest
ln -s '/etc/systemd/system/exectest.service' '/etc/systemd/system/multi-user.target.wants/exectest.service'
$ sudo systemctl start exectest

...然后当我杀死主进程时孩子也死了:

... then the child also dies when I kill the main process:

$ ps -ef | grep exectest | grep -v grep | grep -v vim
snowm     8132     1  0 23:55 ?        00:00:00 /home/snowm/src/exectest/exectest
snowm     8134  8132  0 23:55 ?        00:00:00 /home/snowm/src/exectest/exectest child
$ kill -INT 8132
$ ps -ef | grep exectest | grep -v grep | grep -v vim
$

我怎样才能让孩子活下来?

How can I make the child survive?

在 CentOS Linux release 7.1.1503 (Core) 下运行 go version go1.4.2 linux/amd64.

Running go version go1.4.2 linux/amd64 under CentOS Linux release 7.1.1503 (Core).

推荐答案

解决方案是添加

KillMode=process

到服务块.默认值为 control-group,这意味着 systemd 会清理所有子进程.

to the service block. Default value is control-group which means systemd cleans up any child processes.

来自 man systemd.kill

KillMode= 指定如何终止该单元的进程.之一对照组、过程、混合、无.

KillMode= Specifies how processes of this unit shall be killed. One of control-group, process, mixed, none.

如果设置为control-group,则控制组中的所有剩余进程该单元的 将在单元停止时被杀死(对于服务:停止后命令被执行,配置为 ExecStop=).如果设置为处理,只有主进程本身被杀死.如果设置为混合,则 SIGTERM信号(见下文)被发送到主进程,而随后的SIGKILL 信号(见下文)被发送到所有剩余的进程单位控制组.如果设置为 none,则不会杀死任何进程.在这情况下,停机时只执行停机命令,不执行停机命令否则进程将被杀死.停止后仍然存活的进程是留在他们的控制组中,控制组继续存在停止后,除非它是空的.

If set to control-group, all remaining processes in the control group of this unit will be killed on unit stop (for services: after the stop command is executed, as configured with ExecStop=). If set to process, only the main process itself is killed. If set to mixed, the SIGTERM signal (see below) is sent to the main process while the subsequent SIGKILL signal (see below) is sent to all remaining processes of the unit's control group. If set to none, no process is killed. In this case, only the stop command will be executed on unit stop, but no process be killed otherwise. Processes remaining alive after stop are left in their control group and the control group continues to exist after stop unless it is empty.

这篇关于从systemd启动主进程时无法分离子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆