Files
admin e6956aa001 Initial commit: TaskPool React panel
- React frontend with route-level code splitting
- Backend rebranded from Baihu to TaskPool
- DB brand migration script and local compatibility
2026-07-26 08:43:52 +08:00

102 lines
2.3 KiB
Go

package utils
import (
"os"
"os/exec"
"runtime"
"strings"
"sync"
)
var (
defaultShell string
defaultArgs []string
shellOnce sync.Once
)
// GetShell 返回当前操作系统的 shell 和参数
func GetShell() (shell string, args []string) {
shellOnce.Do(func() {
if runtime.GOOS == "windows" {
defaultShell = "cmd"
defaultArgs = []string{}
return
}
// 1. 优先在 PATH 中查找 bash
if path, err := exec.LookPath("bash"); err == nil {
defaultShell = path
defaultArgs = []string{}
return
}
// 2. 其次使用环境变量中的 SHELL
if envShell := os.Getenv("SHELL"); envShell != "" {
if _, err := os.Stat(envShell); err == nil {
defaultShell = envShell
defaultArgs = []string{}
return
}
}
// 3. 尝试在 PATH 中查找 zsh 或 sh
for _, s := range []string{"zsh", "sh"} {
if path, err := exec.LookPath(s); err == nil {
defaultShell = path
defaultArgs = []string{}
return
}
}
// 4. 最后回退到硬编码路径
shells := []string{"/usr/bin/bash", "/bin/bash", "/usr/bin/sh", "/bin/sh"}
for _, sh := range shells {
if _, err := os.Stat(sh); err == nil {
defaultShell = sh
defaultArgs = []string{}
return
}
}
defaultShell = "sh"
defaultArgs = []string{}
})
return defaultShell, defaultArgs
}
// GetShellCommand 返回执行命令的 shell 和参数
func GetShellCommand(command string) (shell string, args []string) {
shell, _ = GetShell()
if runtime.GOOS == "windows" {
return shell, []string{"/c", command}
}
return shell, []string{"-c", command}
}
// NewShellCmd 创建一个交互式 shell 命令
func NewShellCmd() *exec.Cmd {
shell, _ := GetShell()
if runtime.GOOS == "windows" {
return exec.Command(shell)
}
// Unix 系统使用 -i 启用交互模式
return exec.Command(shell, "-i")
}
// NewShellCommandCmd 创建一个执行指定命令的 shell 命令
func NewShellCommandCmd(command string) *exec.Cmd {
shell, args := GetShellCommand(command)
return exec.Command(shell, args...)
}
// QuotePath 转义并包裹路径,防止 Shell 注入
func QuotePath(path string) string {
if path == "" {
return "''"
}
// 在 Unix-like 系统中,单引号包裹是最安全的
// 需要将路径中的 ' 替换为 '\'' (结束当前引号,转义一个单引号,重新开启引号)
return "'" + strings.ReplaceAll(path, "'", "'\\''") + "'"
}