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

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

问题描述

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

  $ cat exectest.go 
包主

导入(
log
os
os / exec
系统调用
时间


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。运行())
}
}
$构建
$ ./exectest
^ Z
[1] +已停止./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#杀死父进程
[1] +退出2 ./exectest
$ ps -ef | grep exectest | grep -v grep | grep -v vim
snowm 7916 1 0 23:44? 00:00:00 ./exectest child

请注意,父进程之后,子进程仍然存在杀害。但是,如果我从systemd启动这个主进程,像这样...
$ b $ pre $ [snowm @ localhost exectest] $ cat / etc / systemd / system / exectest.service
[单位]
描述= ExecTest

[服务]
类型=简单
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


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

如何让孩子生存下来?



在CentOS Linux release 7.1.1503(Core)下运行go版本go1.4.2 linux / amd64。 解决方案

解决方案是添加

pre $ $ $ c $ KillMode =进程

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


KillMode =指定如何杀死这个单元的进程。
控制组中的一个,过程,混合,无。


如果设置为control-group,控制组中的所有其余进程
该单元将在单元停止时被终止(对于服务:在执行
命令后,使用ExecStop =进行配置)。如果设置为进程,
只有主进程本身被终止。如果设置为混合,则SIGTERM
信号(见下文)被发送到主进程,而随后的
SIGKILL信号(见下文)被发送到
单元控制组的所有其余进程。如果设置为none,则不会终止进程。在这个
的情况下,只有停止命令会在单元停止时执行,但是否则不会有
进程被终止。停止之后剩余的进程在其控制组中保留
,并且控制组在停止后继续存在
,除非它为空。



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

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?

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

解决方案

Solution is to add

KillMode=process

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

From man systemd.kill

KillMode= Specifies how processes of this unit shall be killed. One of control-group, process, mixed, 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天全站免登陆