github.com/gogf/gf/v2@v2.7.4/os/gproc/gproc_shell.go (about) 1 // Copyright GoFrame Author(https://goframe.org). 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/gogf/gf. 6 7 package gproc 8 9 import ( 10 "bytes" 11 "context" 12 "fmt" 13 "io" 14 "runtime" 15 16 "go.opentelemetry.io/otel" 17 "go.opentelemetry.io/otel/propagation" 18 19 "github.com/gogf/gf/v2/os/gfile" 20 ) 21 22 // Shell executes command `cmd` synchronously with given input pipe `in` and output pipe `out`. 23 // The command `cmd` reads the input parameters from input pipe `in`, and writes its output automatically 24 // to output pipe `out`. 25 func Shell(ctx context.Context, cmd string, out io.Writer, in io.Reader) error { 26 p := NewProcess( 27 getShell(), 28 append([]string{getShellOption()}, parseCommand(cmd)...), 29 ) 30 p.Stdin = in 31 p.Stdout = out 32 return p.Run(ctx) 33 } 34 35 // ShellRun executes given command `cmd` synchronously and outputs the command result to the stdout. 36 func ShellRun(ctx context.Context, cmd string) error { 37 p := NewProcess( 38 getShell(), 39 append([]string{getShellOption()}, parseCommand(cmd)...), 40 ) 41 return p.Run(ctx) 42 } 43 44 // ShellExec executes given command `cmd` synchronously and returns the command result. 45 func ShellExec(ctx context.Context, cmd string, environment ...[]string) (result string, err error) { 46 var ( 47 buf = bytes.NewBuffer(nil) 48 p = NewProcess( 49 getShell(), 50 append([]string{getShellOption()}, parseCommand(cmd)...), 51 environment..., 52 ) 53 ) 54 p.Stdout = buf 55 p.Stderr = buf 56 err = p.Run(ctx) 57 result = buf.String() 58 return 59 } 60 61 // parseCommand parses command `cmd` into slice arguments. 62 // 63 // Note that it just parses the `cmd` for "cmd.exe" binary in windows, but it is not necessary 64 // parsing the `cmd` for other systems using "bash"/"sh" binary. 65 func parseCommand(cmd string) (args []string) { 66 return []string{cmd} 67 } 68 69 // getShell returns the shell command depending on current working operating system. 70 // It returns "cmd.exe" for windows, and "bash" or "sh" for others. 71 func getShell() string { 72 switch runtime.GOOS { 73 case "windows": 74 return SearchBinary("cmd.exe") 75 76 default: 77 // Check the default binary storage path. 78 if gfile.Exists("/bin/bash") { 79 return "/bin/bash" 80 } 81 if gfile.Exists("/bin/sh") { 82 return "/bin/sh" 83 } 84 // Else search the env PATH. 85 path := SearchBinary("bash") 86 if path == "" { 87 path = SearchBinary("sh") 88 } 89 return path 90 } 91 } 92 93 // getShellOption returns the shell option depending on current working operating system. 94 // It returns "/c" for windows, and "-c" for others. 95 func getShellOption() string { 96 switch runtime.GOOS { 97 case "windows": 98 return "/c" 99 100 default: 101 return "-c" 102 } 103 } 104 105 // tracingEnvFromCtx converts OpenTelemetry propagation data as environment variables. 106 func tracingEnvFromCtx(ctx context.Context) []string { 107 var ( 108 a = make([]string, 0) 109 m = make(map[string]string) 110 ) 111 otel.GetTextMapPropagator().Inject(ctx, propagation.MapCarrier(m)) 112 for k, v := range m { 113 a = append(a, fmt.Sprintf(`%s=%s`, k, v)) 114 } 115 return a 116 }