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  }