dourao3960 2014-04-12 14:35
浏览 41
已采纳

在Go中启动一个流程并从中分离

I need to start a new process in Go with the following requirements:

  • The starting process should run even after the Go process is terminated
  • I need to be able to set the Unix user/group that's running it
  • I need to be able to set the environment variables inherited
  • I need control over std in/out/err

Here is an attempt:

var attr = os.ProcAttr {
Dir: "/bin",
Env: os.Environ(),
Files: []*os.File{
    os.Stdin,
    "stdout.log",
    "stderr.log",
  },
}
process, err := os.StartProcess("sleep", []string{"1"}, &attr)

This works fine but has the following shortcomings from the requirements:

  • No way to set Unix user/group
  • The started process ends when the Go process (parent) stops

This needs to run on Linux only if that simplifies things.

  • 写回答

2条回答 默认 最新

  • dourong9253 2014-04-29 13:02
    关注
    1. You can use process.Release to detach the child process from the parent one and make it survive after parent death
    2. Look at the definition of *os.ProcAttr.Sys.Credentials attribute : it looks like using the attribute you can set process user and group ID.

    Here is a working version of your example (I did not check if process ID's where actually the one set )

    package main
    
    import "fmt"
    import "os"
    import "syscall"
    
    const (
        UID = 501
        GUID = 100
        )
    
    
    func main() {
        // The Credential fields are used to set UID, GID and attitional GIDS of the process
        // You need to run the program as  root to do this
            var cred =  &syscall.Credential{ UID, GUID, []uint32{} }
        // the Noctty flag is used to detach the process from parent tty
        var sysproc = &syscall.SysProcAttr{  Credential:cred, Noctty:true }
        var attr = os.ProcAttr{
            Dir: ".",
            Env: os.Environ(),
            Files: []*os.File{
                os.Stdin,
                nil,
                nil,
            },
                Sys:sysproc,
    
        }
        process, err := os.StartProcess("/bin/sleep", []string{"/bin/sleep", "100"}, &attr)
        if err == nil {
    
            // It is not clear from docs, but Realease actually detaches the process
            err = process.Release();
            if err != nil {
                fmt.Println(err.Error())
            }
    
        } else {
            fmt.Println(err.Error())
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行