github.com/zhongdalu/gf@v1.0.0/g/os/gproc/gproc.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 // Package gproc implements management and communication for processes. 8 package gproc 9 10 import ( 11 "bytes" 12 "github.com/zhongdalu/gf/g/os/gfile" 13 "github.com/zhongdalu/gf/g/util/gconv" 14 "io" 15 "os" 16 "runtime" 17 "strings" 18 "time" 19 ) 20 21 const ( 22 gPROC_ENV_KEY_PPID_KEY = "GPROC_PPID" 23 gPROC_TEMP_DIR_ENV_KEY = "GPROC_TEMP_DIR" 24 ) 25 26 var ( 27 // 进程开始执行时间 28 processStartTime = time.Now() 29 ) 30 31 // 获取当前进程ID 32 func Pid() int { 33 return os.Getpid() 34 } 35 36 // 获取父进程ID(gproc父进程,如果当前进程本身就是父进程,那么返回自身的pid,不存在时则使用系统父进程) 37 func PPid() int { 38 if !IsChild() { 39 return Pid() 40 } 41 // gPROC_ENV_KEY_PPID_KEY为gproc包自定义的父进程 42 ppidValue := os.Getenv(gPROC_ENV_KEY_PPID_KEY) 43 if ppidValue != "" && ppidValue != "0" { 44 return gconv.Int(ppidValue) 45 } 46 return PPidOS() 47 } 48 49 // 获取父进程ID(系统父进程) 50 func PPidOS() int { 51 return os.Getppid() 52 } 53 54 // 判断当前进程是否为gproc创建的子进程 55 func IsChild() bool { 56 ppidValue := os.Getenv(gPROC_ENV_KEY_PPID_KEY) 57 return ppidValue != "" && ppidValue != "0" 58 } 59 60 // 设置gproc父进程ID,当ppid为0时表示该进程为gproc主进程,否则为gproc子进程 61 func SetPPid(ppid int) error { 62 if ppid > 0 { 63 return os.Setenv(gPROC_ENV_KEY_PPID_KEY, gconv.String(ppid)) 64 } else { 65 return os.Unsetenv(gPROC_ENV_KEY_PPID_KEY) 66 } 67 } 68 69 // 进程开始执行时间 70 func StartTime() time.Time { 71 return processStartTime 72 } 73 74 // 进程已经运行的时间(毫秒) 75 func Uptime() int { 76 return int(time.Now().UnixNano()/1e6 - processStartTime.UnixNano()/1e6) 77 } 78 79 // 阻塞执行shell指令,并给定输入输出对象 80 func Shell(cmd string, out io.Writer, in io.Reader) error { 81 p := NewProcess(getShell(), []string{getShellOption(), cmd}) 82 p.Stdin = in 83 p.Stdout = out 84 return p.Run() 85 } 86 87 // 阻塞执行shell指令,并输出结果当终端(如果需要异步,请使用goroutine) 88 func ShellRun(cmd string) error { 89 p := NewProcess(getShell(), []string{getShellOption(), cmd}) 90 return p.Run() 91 } 92 93 // 阻塞执行shell指令,并返回输出结果(如果需要异步,请使用goroutine) 94 func ShellExec(cmd string) (string, error) { 95 buf := bytes.NewBuffer(nil) 96 p := NewProcess(getShell(), []string{getShellOption(), cmd}) 97 p.Stdout = buf 98 err := p.Run() 99 return buf.String(), err 100 } 101 102 // 检测环境变量中是否已经存在指定键名 103 func checkEnvKey(env []string, key string) bool { 104 for _, v := range env { 105 if len(v) >= len(key) && strings.EqualFold(v[0:len(key)], key) { 106 return true 107 } 108 } 109 return false 110 } 111 112 // 获取当前系统下的shell路径 113 func getShell() string { 114 switch runtime.GOOS { 115 case "windows": 116 return searchBinFromEnvPath("cmd.exe") 117 default: 118 path := searchBinFromEnvPath("bash") 119 if path == "" { 120 path = searchBinFromEnvPath("sh") 121 } 122 return path 123 } 124 } 125 126 // 获取当前系统默认shell执行指令的option参数 127 func getShellOption() string { 128 switch runtime.GOOS { 129 case "windows": 130 return "/c" 131 default: 132 return "-c" 133 } 134 } 135 136 // 从环境变量PATH中搜索可执行文件 137 func searchBinFromEnvPath(file string) string { 138 // 如果是绝对路径,或者相对路径下存在,那么直接返回 139 if gfile.Exists(file) { 140 return file 141 } 142 array := ([]string)(nil) 143 switch runtime.GOOS { 144 case "windows": 145 array = strings.Split(os.Getenv("Path"), ";") 146 if gfile.Ext(file) != ".exe" { 147 file += ".exe" 148 } 149 default: 150 array = strings.Split(os.Getenv("PATH"), ":") 151 } 152 if len(array) > 0 { 153 for _, v := range array { 154 path := v + gfile.Separator + file 155 if gfile.Exists(path) { 156 return path 157 } 158 } 159 } 160 return "" 161 }