go语言执行shell命令的一个bug

EddieChan1993 · 2018-08-23 21:42:29 · 2733 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-08-23 21:42:29 的主题,其中的信息可能已经有所发展或是发生改变。

问题

执行这个函数时execShell("nohup ./hatgo &")&exec.Command自动屏蔽了,导致最后应用无法后台运行 ,麻烦大家给我指教一下。

func execShell(s string) {
    cmd := exec.Command("sh", "-c", s)
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    checkErr(err, out.String())
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2733 次点击  
加入收藏 微博
10 回复  |  直到 2018-10-16 12:01:08
jarlyyn
jarlyyn · #1 · 6年之前

bug..... 你现要了解&有什么用。 带&和不带&,其实就相当于 go里你是用run还是start来开始程序。

或者直接go起个协助程来跑就可以了。

EddieChan1993
EddieChan1993 · #2 · 6年之前
jarlyynjarlyyn #1 回复

bug..... 你现要了解&有什么用。 带&和不带&,其实就相当于 go里你是用run还是start来开始程序。 或者直接go起个协助程来跑就可以了。

你没理解到我的意思,我既然选择shell来执行,肯定有要我的用处嘛,我是用来后台运行go应用,通过这个命令实现常住。

jarlyyn
jarlyyn · #3 · 6年之前

jarlyyn@debian:/tmp/go$ cat test.go package main

import ( "fmt" "os/exec" "time" )

func main() { cmd := exec.Command("sh", "-c", "tail -f 1.txt") go func() { fmt.Println(cmd.Run()) }() time.Sleep(time.Second) } jarlyyn@debian:/tmp/go$ ps -A|grep tail jarlyyn@debian:/tmp/go$ go run test.go jarlyyn@debian:/tmp/go$ ps -A|grep tail 14758 pts/5 00:00:00 tail jarlyyn@debian:/tmp/go$

jarlyyn
jarlyyn · #4 · 6年之前

Screenshot_20180824_123719.png

打一段字回复前,可能跑个简单的测试程序效率更高。

EddieChan1993
EddieChan1993 · #5 · 6年之前
jarlyynjarlyyn #4 回复

![Screenshot_20180824_123719.png](https://static.studygolang.com/180824/7cadc20f9c8b1768429c7886b6ebdaa3.png) 打一段字回复前,可能跑个简单的测试程序效率更高。

谢谢你的回复,但是我问题的重点是nohup &这个命令通过go调用shell包正确执行的问题。

jarlyyn
jarlyyn · #6 · 6年之前

Screenshot_20180824_143108.png

zhu-dq
zhu-dq · #7 · 6年之前

请问这个问题你最终是怎么解决的?我也遇到了一个类似问题

rwdysilent
rwdysilent · #8 · 6年之前

我也遇到了这个问题,已经解决

首先,这不是一个bug 其次,这个现象是因为你go程序运行( 主程A),启动shell子进程B, A是B的父进程,父进程退出,B就跟着退出了,B并没有被init 1进程接管,这是导致这个问题的原因

解决方案:

  1. nohup命令是为了让程序忽略hangup 信号, 这里这样使用不太合适。我们的目的是为了A退出后,B能够被init 1进程接管,所以可以换一种方式,修改shell命令,使用setsid让其后台运行。比如: setsid tail -f 1.txt 参考文档: https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/
  2. go程序exec有一种方式, 可以通过在Cmd.SysProcAttr字段中将Setpgid设置为true来实现, 这种方式我没有实际尝试,楼主可以自行尝试下,然后可以分享出来,原理是一样的
EddieChan1993
EddieChan1993 · #9 · 6年之前
zhu-dqzhu-dq #7 回复

请问这个问题你最终是怎么解决的?我也遇到了一个类似问题

我最后把他改成了这样

    cmd := exec.Command("sh", "-c", s)
    err := cmd.Run()
    checkErr(err, "")
EddieChan1993
EddieChan1993 · #10 · 6年之前
rwdysilentrwdysilent #8 回复

我也遇到了这个问题,已经解决 首先,这不是一个bug 其次,这个现象是因为你go程序运行( 主程A),启动shell子进程B, A是B的父进程,父进程退出,B就跟着退出了,B并没有被init 1进程接管,这是导致这个问题的原因 解决方案: 1. nohup命令是为了让程序忽略hangup 信号, 这里这样使用不太合适。我们的目的是为了A退出后,B能够被init 1进程接管,所以可以换一种方式,修改shell命令,使用setsid让其后台运行。比如: setsid tail -f 1.txt 参考文档: https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/ 2. go程序exec有一种方式, 可以通过在Cmd.SysProcAttr字段中将Setpgid设置为true来实现, 这种方式我没有实际尝试,楼主可以自行尝试下,然后可以分享出来,原理是一样的

谢谢你的建议。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传