Go Syscall


原文链接: Go Syscall

Golang-too_many_open_files

// 方式一:
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &syscall.Rlimit{Cur: 1000000, Max: 1000000}); err != nil {
		panic(err)
	}
//方式二:
var rlimit syscall.Rlimit
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit)
if err != nil {
    fmt.Println("get rlimit error: " + err.Error())
    os.Exit(1)
}
rlimit.Cur = 50000 //以字节为单位
rlimit.Max = rlimit.Cur + 1024

err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)

if err != nil {
    fmt.Println("set rlimit error: " + err.Error())
    os.Exit(1)
}

使用 go build 编译后,需要以 root 权限运行。

Killing a child process and all of its children in Go

Go是使用kill(2)向sh进程的PID发了一个KILL信号,但没有发给watch进程,sh进程被kill之后,导致watch进程变成孤儿进程。实际这是unix编程语言的一个非常正常的行为,只是...在很多场景下确实不适用。

  • 解决方案

kill(2)不但支持向单个PID发送信号,还可以向进程组发信号,传递进程组PGID的时候要使用负数的形式。我们只要把sh进程及其所有子进程放到一个进程组里,就可以批量Kill了。关键是PGID的设置,默认情况下,子进程会把自己的PGID设置成与父进程相同,所以,我们只要设置了sh进程的PGID,所有子进程也就相应的有了PGID。

package main

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

func main() {
    cmd := exec.Command("/bin/sh", "-c", "watch date > date.txt")
    // Go会将PGID设置成与PID相同的值,防止sh进程结束后,watch进程变成孤儿进程
    cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
    start := time.Now()
    time.AfterFunc(3*time.Second, func() { syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) })
    err := cmd.Run()
    fmt.Printf("pid=%d duration=%s err=%s\n", cmd.Process.Pid, time.Since(start), err)
}
`