Files
1Panel/agent/utils/cmd/cmd.go

109 lines
2.7 KiB
Go

package cmd
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strings"
"sync"
)
var (
sudoHandleCmd string
sudoCheckOnce sync.Once
)
func CheckIllegal(args ...string) bool {
if args == nil {
return false
}
for _, arg := range args {
if strings.Contains(arg, "&") || strings.Contains(arg, "|") || strings.Contains(arg, ";") ||
strings.Contains(arg, "$") || strings.Contains(arg, "'") || strings.Contains(arg, "`") ||
strings.Contains(arg, "(") || strings.Contains(arg, ")") || strings.Contains(arg, "\"") ||
strings.Contains(arg, "\n") || strings.Contains(arg, "\r") || strings.Contains(arg, ">") || strings.Contains(arg, "<") {
return true
}
}
return false
}
func SudoHandleCmd() string {
sudoCheckOnce.Do(func() {
cmd := exec.Command("sudo", "-n", "ls")
if err := cmd.Run(); err == nil {
sudoHandleCmd = "sudo "
}
})
return sudoHandleCmd
}
func WrapWithOptionalSudo(name string, args ...string) (string, []string) {
if SudoHandleCmd() == "" {
return name, args
}
return "sudo", append([]string{"-n", name}, args...)
}
func ExecCommandWithOptionalSudo(name string, args ...string) *exec.Cmd {
commandName, commandArgs := WrapWithOptionalSudo(name, args...)
return exec.Command(commandName, commandArgs...)
}
func WriteFileWithOptionalSudo(name string, data []byte, perm os.FileMode) error {
if err := os.WriteFile(name, data, perm); err == nil {
return nil
} else if SudoHandleCmd() == "" {
return err
}
command := exec.Command("sudo", "-n", "tee", name)
command.Stdin = bytes.NewReader(data)
command.Stdout = io.Discard
return command.Run()
}
func Which(name string) bool {
_, err := exec.LookPath(name)
return err == nil
}
func commandStartDiagnostics(name, resolvedName, workDir string, env []string) string {
items := []string{
fmt.Sprintf("command=%q", name),
fmt.Sprintf("resolved=%q", resolvedName),
fmt.Sprintf("path=%q", envValue(env, "PATH")),
}
if workDir != "" {
items = append(items, describeWorkDir(workDir))
}
return "; " + strings.Join(items, "; ")
}
func describeWorkDir(name string) string {
statText := "stat=ok"
if info, err := os.Stat(name); err != nil {
statText = fmt.Sprintf("stat=%v", err)
} else {
statText = fmt.Sprintf("stat=mode:%s", info.Mode().String())
}
lstatText := "lstat=ok"
if info, err := os.Lstat(name); err != nil {
lstatText = fmt.Sprintf("lstat=%v", err)
} else {
lstatText = fmt.Sprintf("lstat=mode:%s", info.Mode().String())
}
return fmt.Sprintf("workdir=%q[%s %s]", name, statText, lstatText)
}
func envValue(env []string, key string) string {
prefix := key + "="
for i := len(env) - 1; i >= 0; i-- {
if strings.HasPrefix(env[i], prefix) {
return strings.TrimPrefix(env[i], prefix)
}
}
return os.Getenv(key)
}