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  }