package main
import (
"log"
"os"
"bufio"
"github.com/docker/docker/pkg/reexec"
"os/exec"
"sync"
)
func init() {
log.Printf("init start, os.Args = %+v\n", os.Args)
reexec.Register("childProcess", childProcess)
if reexec.Init() {
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
os.Exit(0)
}
}
func childProcess() {
log.Println("childProcess")
}
func main() {
log.Printf("main start, os.Args = %+v\n", os.Args)
cmd :=make([]*exec.Cmd,5)
var wg sync.WaitGroup
wg.Add(5)
for i:=0;i<5;i++{
go func(i int,cmd []*exec.Cmd){
cmd[i] = reexec.Command("childProcess")
cmd[i] .Stdin = os.Stdin
cmd[i] .Stdout = os.Stdout
cmd[i] .Stderr = os.Stderr
if err := cmd[i] .Start(); err != nil {
log.Panicf("failed to run command: %s", err)
}
log.Println("started,begin to wait...",i)
wg.Done()
}(i,cmd)
}
wg.Wait()
for j:=0;j<5;j++{
if err := cmd[j] .Wait(); err != nil {
log.Panicf("failed to wait command[%d]: %s", j,err)
}
}
log.Println("main exit")
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
}
或者:
package main
import (
"bufio"
"fmt"
"github.com/vishvananda/netns"
"log"
"net"
"os"
"os/exec"
"runtime"
"strconv"
"sync"
"reflect"
"unsafe"
)
func init() {
if len(os.Args) > 1 {
SetProcessName(os.Args[1]+" process")
}
}
func SetProcessName(name string) error {
argv0str := (*reflect.StringHeader)(unsafe.Pointer(&os.Args[0]))
//log.Println("old process name:",argv0str)
argv0 := (*[1 << 30]byte)(unsafe.Pointer(argv0str.Data))[:argv0str.Len]
n := copy(argv0, name)
if n < len(argv0) {
for k:=n;k<len(argv0);k++{
argv0[k] = 0
}
}
return nil
}
func main() {
log.Printf("main start, os.Args = %+v , processID:%d \n", os.Args, os.Getpid())
param := "run"
if len(os.Args) > 1 {
param = os.Args[1]
}
switch param {
case "run":
parent()
case "child":
child()
default:
panic("wat should I do")
}
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
//for;;{
// time.Sleep(time.Millisecond*1000)
//}
}
func parent() {
childNum := 2
cmd := make([]*exec.Cmd, childNum)
var wg sync.WaitGroup
wg.Add(childNum)
for i := 0; i < childNum; i++ {
go func(i int, cmd []*exec.Cmd) {
cmd[i] = exec.Command("/proc/self/exe", append(append([]string{"child"}), strconv.Itoa(i))...)
cmd[i].Stdin = os.Stdin
cmd[i].Stdout = os.Stdout
cmd[i].Stderr = os.Stderr
if err := cmd[i].Run(); err != nil {
fmt.Println("ERROR", err)
os.Exit(1)
}
}(i, cmd)
wg.Done()
}
wg.Wait()
log.Println("Parent process running,pid:", os.Getpid())
}
func child() {
//cmd := exec.Command("/proc/self/exe",os.Args...)
//cmd.Stdin = os.Stdin
//cmd.Stdout = os.Stdout
//cmd.Stderr = os.Stderr
//
//if err := cmd.Run(); err != nil {
// fmt.Println("ERROR", err)
// os.Exit(1)
//}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
go func() {
log.Println("childProcess begin...", os.Args[1])
origns, _ := netns.Get()
defer origns.Close()
log.Println("origin namespace:", origns.String())
newNS, err := netns.GetFromName("net" + os.Args[2])
if err != nil {
log.Println("get ns err:", err.Error())
}
log.Println("pid:", os.Getpid(), " new namespace :", newNS.UniqueId())
netns.Set(newNS)
defer newNS.Close()
ifaces, _ := net.Interfaces()
log.Println(fmt.Sprintf("Interfaces: %v\n", ifaces))
nowNS, err := netns.Get()
if err != nil {
log.Println("get ns failed:", err.Error())
}
log.Println("final orig namespace :", nowNS.UniqueId())
}()
log.Println("Child process running,pid:", os.Getpid())
}
func must(err error) {
if err != nil {
panic(err)
}
}