首页 > 解决方案 > 如何在单独的进程中启动应用程序“分离”。启动的进程必须在它自己的会话中运行并且像一个守护进程一样运行

问题描述

有谁知道如何在 golang (Go) 中运行分离命令?

任务是:我有 app1 和 app2,app2 做大而长的工作,大约。2 小时。但是 app1 是默认应用程序,它可以在几分钟内完成工作,每天调用 1-2 次。实际上,我需要运行 app1,而不是在 app1 gorutine 中运行 app2,app1 将完成其工作并关闭,但 app2 必须仍然工作,直到其任务列表结束。如果运行 2-3 个 app2 实例,这可能是正常情况。

我需要smth。像这样,我在 bash 中做什么:

$ ./my-app &

...或在 Qt 中:

QProcess prc;
prc.setArguments(args);
prc.setProgram(app2);
prc.setWorkingDirectory(dir);
prc.startDetached();

Qt 文档:

bool QProcess::startDetached(qint64 *pid = nullptr)

在新进程中使用参数启动程序,并从中分离...如果调用进程退出,分离的进程将继续运行而不受影响。启动的进程将在其自己的会话中运行,并像一个守护进程一样运行。如果函数成功,则 *pid 设置为已启动进程的进程标识符。请注意,子进程可能会退出,PID 可能会变为无效,恕不另行通知。此外,子进程退出后,同一个PID可能会被完全不同的进程回收使用。

所以,我在 Go 中这样做:

    cmd := exec.Command("./app2", "&")
    _ = cmd.Run()

...但它没有帮助,'app2' 仍然没有分离。如果我从运行“app2”的地方杀死主app1,那么“app2”也将被关闭。

我也尝试过这种方式:(在app1中)

    var attr = os.ProcAttr{
        Dir: ".",
        Env: os.Environ(),
        Files: []*os.File{
            os.Stdin,
            os.Stdout,
            os.Stderr,
        },
    }
    process, err := os.StartProcess(server, []string{"/usr/local/app2"}, &attr)

    if err == nil {
        err = process.Release()
    }
    if err != nil {
        log.Println(err)
    }

并且可以告诉,它也不起作用。

现在我只有一个解决方案:使用 ListenAndServe 将 app2 设为服务器,然后在 app1 中运行 app2,不管如何,但在 gorutine 中:

go func() {
    cmd := exec.Command("/usr/local/app2")
    _ = cmd.Run()
}()

并在 bash 中将 app1 作为独立进程运行:

./app1 &

在这种情况下,app1 将运行 app2,完成所有工作并关闭,但 app2 将完成所有长期工作。

实际上,我想在 golang(Go 语言)中做与 Qt 中的 QProcess::startDetached 相同的操作(用于扩展 C++ 语言的跨平台应用程序开发框架)

PS。Golang(或 Go,对于在使用 Golang 单词的情况下心脏病发作的语法纳粹分子):顺便说一句,“不过,许多人使用 golang 名称,它作为标签很方便” https://golang.org/doc /常见问题解答#go_or_golang

标签: go

解决方案


在 linux go 版本 1.15.2 上,我运行下面的代码,它会产生一个不会随 main 死的新进程。

package main

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

func main() {
    cmd := exec.Command("go", "run", "./d")
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    log.Printf("Running command and waiting for it to finish...")
    err := cmd.Start()
    if err != nil {
        log.Fatal("cmd.Start failed: ", err)
    }
    err = cmd.Process.Release()
    if err != nil {
        log.Fatal("cmd.Process.Release failed: ", err)
    }
}

./d/main.go在哪里

package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        for {
            fmt.Println("hop")
            <-time.After(time.Second)
        }
    }()
    <-make(chan bool)
}

推荐阅读