当前位置: 首页 > news >正文

福州市建设工程质量监督站网站谁做彩票网站代理

福州市建设工程质量监督站网站,谁做彩票网站代理,长沙住房建设部网站,网站配色分析简介#xff1a; 在 Go 程序当中#xff0c;如果我们要执行命令时#xff0c;通常会使用 exec.Command #xff0c;也比较好用#xff0c;通常状况下#xff0c;可以达到我们的目的#xff0c;如果我们逻辑当中#xff0c;需要终止这个进程#xff0c;则可以快速使用 …简介 在 Go 程序当中如果我们要执行命令时通常会使用 exec.Command 也比较好用通常状况下可以达到我们的目的如果我们逻辑当中需要终止这个进程则可以快速使用 cmd.Process.Kill() 方法来结束进程。但当我们要执行的命令会启动其他子进程来操作的时候会发生什么情况 作者 | 昕希 来源 | 阿里技术公众号 在 Go 程序当中如果我们要执行命令时通常会使用 exec.Command 也比较好用通常状况下可以达到我们的目的如果我们逻辑当中需要终止这个进程则可以快速使用 cmd.Process.Kill() 方法来结束进程。但当我们要执行的命令会启动其他子进程来操作的时候会发生什么情况 一 孤儿进程的产生 测试小程序 func kill(cmd *exec.Cmd) func() {return func() {if cmd ! nil {cmd.Process.Kill()}} }func main() {cmd : exec.Command(/bin/bash, -c, watch top top.log)time.AfterFunc(1*time.Second, kill(cmd))err : cmd.Run()fmt.Printf(pid%d err%s\n, cmd.Process.Pid, err) } 执行小程序 go run main.gopid27326 errsignal: killed 查看进程信息 ps -jUSER PID PPID PGID SESS JOBC STAT TT TIME COMMAND king 24324 1 24303 0 0 S s012 0:00.01 watch top 可以看到这个 watch top 的 PPID 为 1说明这个进程已经变成了 “孤儿” 进程。 那为什么会这样这并不符合我们预期那么可以从 Go 的文档中找到答案 二 通过进程组来解决掉所有子进程 在 linux 当中是有会话、进程组和进程组的概念并且 Go 也是使用 linux 的 kill(2) 方法来发送信号的那么是否可以通过 kill 来将要结束进程的子进程都结束掉 linux 的 kill(2) 的定义如下 并在方法的描述中可以看到如下内容 如果 pid 为正数的时候会给指定的 pid 发送 sig 信号如果 pid 为负数的时候会给这个进程组发送 sig 信号那么我们可以通过进程组来将所有子进程退出掉改一下 Go 程序中 kill 方法 func kill(cmd *exec.Cmd) func() {return func() {if cmd ! nil {// cmd.Process.Kill()syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)}} }func main() {cmd : exec.Command(/bin/bash, -c, watch top top.log)time.AfterFunc(1*time.Second, kill(cmd))err : cmd.Run()fmt.Printf(pid%d err%s\n, cmd.Process.Pid, err) } 再次执行 go run main.go 会发现程序卡住了我们来看一下当前执行的进程 ps -jUSER PID PPID PGID SESS JOBC STAT TT TIME COMMAND king 27655 91597 27655 0 1 S s012 0:01.10 go run main.go king 27672 27655 27655 0 1 S s012 0:00.03 ..../exe/main king 27673 27672 27655 0 1 S s012 0:00.00 /bin/bash -c watch top top.log king 27674 27673 27655 0 1 S s012 0:00.01 watch top 可以看到我们 go run 产生了一个子进程 27672command 那里是 go 执行的临时目录比较长因此添加了省略号27672 产生了 27673watch top top.log进程27673 产生了 27674watch top进程。那为什么没有将这些子进程都关闭掉呢 其实之类犯了一个低级错误从上图中我们可以看到他们的进程组 ID 为 27655但是我们传递的是 cmd 的 id 即 27673这个并不是进程组的 ID因此程序并没有 kill导致 cmd.Run() 一直在执行。 在 Linux 中进程组中的第一个进程被称为进程组 Leader同时这个进程组的 ID 就是这个进程的 ID从这个进程中创建的其他进程都会继承这个进程的进程组和会话信息从上面可以看出 go run main.go 程序 PID 和 PGID 同为 27655那么这个进程就是进程组 Leader我们不能 kill 这个进程组除非想“自杀”哈哈哈。 那么我们给要执行的进程新建一个进程组在 Kill 不就可以了嘛。在 linux 当中通过 setpgid 方法来设置进程组 ID定义如下 如果将 pid 和 pgid 同时设置成 0也就是 setpgid(0,0)则会使用当前进程为进程组 leader 并创建新的进程组。 那么在 Go 程序中可以通过 cmd.SysProcAttr 来设置创建新的进程组修改后的代码如下 func kill(cmd *exec.Cmd) func() {return func() {if cmd ! nil {// cmd.Process.Kill()syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)}} }func main() {cmd : exec.Command(/bin/bash, -c, watch top top.log)cmd.SysProcAttr syscall.SysProcAttr{Setpgid: true,}time.AfterFunc(1*time.Second, kill(cmd))err : cmd.Run()fmt.Printf(pid%d err%s\n, cmd.Process.Pid, err) } 再次执行 go run main.gopid29397 errsignal: killed 再次查看进程 ps -jUSER PID PPID PGID SESS JOBC STAT TT TIME COMMAND 发现 watch 的进程都不存在了那我们在看看是否还会有孤儿进程 # 由于我测试的环境是mac因此这个脚本只能在mac执行 ps -j | head -1;ps -j | awk {if ($3 1 $1 !root){print $0}} | headUSER PID PPID PGID SESS JOBC STAT TT TIME COMMAND 已经没有孤儿进程了问题至此已经完全解决。 三 子进程监听父进程是否退出(只能在 linux 下执行) 假设要调用的程序也是我们自己写的其他应用程序那么可以使用 Linux 的 prctl 方法来处理 prctl 方法的定义如下 这个方法有一个重要的 optionPR_SET_PDEATHSIG通过这个来接收父进程的退出。 让我们来再次构造一个有问题的程序。 有两个文件分别为 main.go 和 child.go 文件main.go 会调用 child.go 文件。 main.go 文件 package mainimport (os/exec )func main() {cmd : exec.Command(./child)cmd.Run() } child.go 文件 package mainimport (fmttime )func main() {for {time.Sleep(200 * time.Millisecond)fmt.Println(time.Now())} } 在 Linux 环境中分别编译这两个文件 // 编译 main.go 生成 main 二进制文件 go build -o main main.go// 编译 child.go 生成 child 二进制文件 go build -o child child.go 执行 main 二进制文件 ./main 查看他们的进程 ps -efUID PID PPID C STIME TTY TIME CMD root 1 0 0 06:05 pts/0 00:00:00 /bin/bash root 11514 1 0 12:12 pts/0 00:00:00 ./main root 11520 11514 0 12:12 pts/0 00:00:00 ./child 可以看到 main 和 child 的进程child 是 main 的子进程我们将 main 进程 kill 掉在查看进程状态 kill -9 11514ps -efUID PID PPID C STIME TTY TIME CMD root 1 0 0 06:05 pts/0 00:00:00 /bin/bash root 11520 1 0 12:12 pts/0 00:00:00 ./child 我们可以看到 child 的进程他的 PPID 已经变成了 1说明这个进程已经变成了孤儿进程。 那接下来我们可以使用 PR_SET_PDEATHSIG 来保证父进程退出子进程也退出大致方式有两种使用 CGO 调用和使用 syscall.RawSyscall 来调用。 1 使用 CGO 将 child 修改成如下内容 程序中使用 CGO为了简单的展示在 Go 文件中编写了 C 的 killTest 方法并调用了 prctl 方法然后在 Go 程序中调用 killTest 方法让我们重新编译执行一下再看看进程 go build -o child child.go ./main ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 06:05 pts/0 00:00:00 /bin/bash root 11663 1 0 12:28 pts/0 00:00:00 ./main root 11669 11663 0 12:28 pts/0 00:00:00 ./child 再次 kill 掉 main并查看进程 kill -9 11663 ps -efUID PID PPID C STIME TTY TIME CMD root 1 0 0 06:05 pts/0 00:00:00 /bin/bash 可以看到 child 的进程也已经退出了说明 CGO 调用的 prctl 生效了。 2 syscall.RawSyscall 方法 也可以采用 Go 中提供的 syscall.RawSyscall 方法来替代调用 CGO在 Go 的文档中可以查看到 syscall 包中定义的常量查看 linux如果是本地 godoc需要指定 GOOSlinux可以看到我们要用的几个常量以及他们对应的数值 // 其他内容省略掉了 const(....PR_SET_PDEATHSIG 0x1.... )const( .....SYS_PRCTL 157..... ) 其中 PR_SET_PDEATHSIG 操作的值为 1SYS_PRCTL 的值为 157那么将 child.go 修改成如下内容 package mainimport (fmtossyscalltime )func main() {_, _, errno : syscall.RawSyscall(uintptr(syscall.SYS_PRCTL), uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGKILL), 0)if errno ! 0 {os.Exit(int(errno))}for {time.Sleep(200 * time.Millisecond)fmt.Println(time.Now())} } 再次编译并执行 go build -o child child.go ./main ps -efUID PID PPID C STIME TTY TIME CMD root 1 0 0 06:05 pts/0 00:00:00 /bin/bash root 12208 1 0 12:46 pts/0 00:00:00 ./main root 12214 12208 0 12:46 pts/0 00:00:00 ./child 将 main 进程结束掉 kill -9 12208 ps -efUID PID PPID C STIME TTY TIME CMD root 1 0 0 06:05 pts/0 00:00:00 /bin/bash child 进程已经退出了也达成了最终效果。 四 总结 当我们使用 Go 程序执行其他程序的时候如果其他程序也开启了其他进程那么在 kill 的时候可能会把这些进程变成孤儿进程一直执行并滞留在内存中。当然如果我们程序非法退出或者被 kill 调用也会导致我们执行的进程变成孤儿进程那么为了解决这个问题从两个思路来解决 给要执行的程序创建新的进程组并调用 syscall.Kill传递负值 pid 来关闭这个进程组中所有的进程比较完美的解决方法。如果要调用的程序也是我们自己编写的那么可以使用 PR_SET_PDEATHSIG 来感知父进程退出那么这种方式需要调用 Linxu 的 prctrl可以使用 CGO 的方式也可以使用 syscall.RawSyscall 的方式。 但不管使用哪种方式都只是提供了一种思路在我们编写服务端服务程序的时候需要特殊关注防止孤儿进程消耗服务器资源。 原文链接 本文为阿里云原创内容未经允许不得转载。
http://www.zqtcl.cn/news/868408/

相关文章:

  • 建站设计公司wordpress 跨域 cros
  • 做网站的公司哪好工程设计东莞网站建设技术支持
  • 虹口网站开发开发公司设计管理部绩效考核
  • 网站改版升级通知国外服务器公司有哪些
  • 做网站的s标的软件深圳网站建设 湖南岚鸿
  • 设计网站建设的合同书公司装修合同范本
  • 门户网站的好处企业邮箱系统
  • 重庆企业建站公司有那些网站做结伴旅游的
  • 创意营销策划案例网站网页制作及优化
  • 网站上动画视频怎么做的建设兵团12师教育局网站
  • 博客网站开发思维导图app网站制作公司
  • 池州网站建设有哪些公司兴义网站seo
  • seo优化网站模板网站建设的七大优缺点
  • 天猫国际采取的跨境电商网络营销方式关键词排名优化公司推荐
  • 亳州建设网站做网站文字怎么围绕图片
  • 网站开发 项目计划外链建设给网站起的作用
  • 你好南京网站网站开发实施步骤和说明
  • 文化共享工程网站建设情况wordpress菠菜插件
  • 网站大气是什么意思哈尔滨做网站电话
  • 公司网站站群是什么化妆品网站设计欣赏
  • 网站公司未来计划ppt怎么做平潭做网站
  • 做网站和推广工资多少招聘网站建设价格
  • 网站建设 响应式 北京网架公司十大排名榜
  • 网站推广目标关键词是什么意思网站推广软件工具
  • 哪里可以做免费的物流网站wordpress为什么放弃
  • 做网站需要多少钱 都包括什么高端大气的网站首页
  • 黄石做网站联系最近的国际新闻
  • 网站建设与运营的预算方案淘宝禁止了网站建设类
  • 做网站的顺序编写app的软件
  • 站长联盟个人网站不备案