mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 08:00:53 +00:00
refactor: update agent and core utilities (#12621)
This commit is contained in:
committed by
zhengkunwang223
parent
84a27de792
commit
d55982bde0
@@ -990,7 +990,7 @@ func validateAgentConfigFileContent(agentType, content string) error {
|
||||
}
|
||||
|
||||
func getOpenclawNPMRegistry(containerName string) (string, error) {
|
||||
registry, err := runDockerExecWithStdout(20*time.Second, containerName, "npm", "get", "registry")
|
||||
registry, err := cmd.RunDockerExecWithStdout(20*time.Second, containerName, "npm", "get", "registry")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1002,7 +1002,7 @@ func getOpenclawNPMRegistry(containerName string) (string, error) {
|
||||
}
|
||||
|
||||
func setOpenclawNPMRegistry(containerName, registry string) error {
|
||||
return cmd.RunDefaultBashCf("docker exec %s npm set registry %q", containerName, registry)
|
||||
return cmd.NewCommandMgr().Run("docker", "exec", containerName, "npm", "set", "registry", registry)
|
||||
}
|
||||
|
||||
func (a AgentService) loadAgentAndInstall(agentID uint) (*model.Agent, *model.AppInstall, error) {
|
||||
|
||||
@@ -23,7 +23,7 @@ func (a AgentService) CreateRole(req dto.AgentRoleCreateReq) (*dto.AgentRoleCrea
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args := []string{"exec", install.ContainerName, "openclaw", "agents", "add", req.Name}
|
||||
args := []string{"openclaw", "agents", "add", req.Name}
|
||||
workspace := "/home/node/.openclaw/workspace-agent_" + req.Name
|
||||
agentDir := "/home/node/.openclaw/agents/" + req.Name
|
||||
args = append(args, "--workspace", workspace)
|
||||
@@ -43,8 +43,7 @@ func (a AgentService) CreateRole(req dto.AgentRoleCreateReq) (*dto.AgentRoleCrea
|
||||
args = append(args, "--agent-dir", agentDir)
|
||||
args = append(args, "--non-interactive", "--json")
|
||||
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Minute))
|
||||
output, err := mgr.RunWithStdout("docker", args...)
|
||||
output, err := cmd.RunDockerExecWithStdout(5*time.Minute, install.ContainerName, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -125,10 +124,8 @@ func (a AgentService) DeleteRole(req dto.AgentRoleDeleteReq) error {
|
||||
return buserr.New("ErrRecordNotFound")
|
||||
}
|
||||
|
||||
args := []string{"exec", install.ContainerName, "openclaw", "agents", "delete", req.ID, "--force"}
|
||||
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Minute))
|
||||
if _, err = mgr.RunWithStdout("docker", args...); err != nil {
|
||||
args := []string{"openclaw", "agents", "delete", req.ID, "--force"}
|
||||
if _, err = cmd.RunDockerExecWithStdout(5*time.Minute, install.ContainerName, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
if target.Workspace != "" {
|
||||
@@ -171,8 +168,6 @@ func (a AgentService) operateRoleBinding(req dto.AgentRoleBindReq, action string
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
args := []string{
|
||||
"exec",
|
||||
install.ContainerName,
|
||||
"openclaw",
|
||||
"agents",
|
||||
action,
|
||||
@@ -182,8 +177,7 @@ func (a AgentService) operateRoleBinding(req dto.AgentRoleBindReq, action string
|
||||
binding,
|
||||
}
|
||||
args = append(args, "--json")
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Minute))
|
||||
_, err = mgr.RunWithStdout("docker", args...)
|
||||
_, err = cmd.RunDockerExecWithStdout(5*time.Minute, install.ContainerName, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -372,14 +372,14 @@ func (a AgentService) InstallPlugin(req dto.AgentPluginInstallReq) error {
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute))
|
||||
if req.Type == "qqbot" {
|
||||
legacyPluginPath := path.Join(openclawPluginBaseDir, "qqbot")
|
||||
if err := mgr.RunBashCf("docker exec %s test -d %s", install.ContainerName, legacyPluginPath); err == nil {
|
||||
if _, err := mgr.RunWithStdout("docker", "exec", "-i", install.ContainerName, "sh", "-c", buildOpenclawPluginUninstallScript("qqbot")); err != nil {
|
||||
if err := mgr.Run("docker", "exec", install.ContainerName, "test", "-d", legacyPluginPath); err == nil {
|
||||
if err := uninstallOpenclawPlugin(mgr, install.ContainerName, "qqbot"); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
if _, err := mgr.RunWithStdout("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawPluginInstallScript(spec, pluginID)); err != nil {
|
||||
if err := installOpenclawPlugin(mgr, install.ContainerName, spec, pluginID); err != nil {
|
||||
return err
|
||||
}
|
||||
conf, err := readOpenclawConfig(agent.ConfigPath)
|
||||
@@ -415,11 +415,11 @@ func (a AgentService) UpgradePlugin(req dto.AgentPluginUpgradeReq) error {
|
||||
}
|
||||
upgradeTask.AddSubTask("Upgrade OpenClaw plugin", func(t *task.Task) error {
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute))
|
||||
if _, err := mgr.RunWithStdout("docker", "exec", "-i", install.ContainerName, "sh", "-c", buildOpenclawPluginUninstallScript(pluginID)); err != nil {
|
||||
if err := uninstallOpenclawPlugin(mgr, install.ContainerName, pluginID); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
if _, err := mgr.RunWithStdout("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawPluginInstallScript(spec, pluginID)); err != nil {
|
||||
if err := installOpenclawPlugin(mgr, install.ContainerName, spec, pluginID); err != nil {
|
||||
return err
|
||||
}
|
||||
conf, err := readOpenclawConfig(agent.ConfigPath)
|
||||
@@ -455,7 +455,7 @@ func (a AgentService) UninstallPlugin(req dto.AgentPluginUninstallReq) error {
|
||||
}
|
||||
uninstallTask.AddSubTask("Uninstall OpenClaw plugin", func(t *task.Task) error {
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(10*time.Minute))
|
||||
if _, err := mgr.RunWithStdout("docker", "exec", "-i", install.ContainerName, "sh", "-c", buildOpenclawPluginUninstallScript(pluginID)); err != nil {
|
||||
if err := uninstallOpenclawPlugin(mgr, install.ContainerName, pluginID); err != nil {
|
||||
return err
|
||||
}
|
||||
conf, err := readOpenclawConfig(agent.ConfigPath)
|
||||
@@ -487,7 +487,7 @@ func (a AgentService) LoginWeixinChannel(req dto.AgentWeixinLoginReq) error {
|
||||
if agent.AgentType == constant.AppHermesAgent {
|
||||
return mgr.Run("docker", buildHermesWeixinLoginArgs(install.ContainerName)...)
|
||||
}
|
||||
return mgr.RunBashCf("docker exec %s openclaw channels login --channel openclaw-weixin", install.ContainerName)
|
||||
return mgr.Run("docker", "exec", install.ContainerName, "openclaw", "channels", "login", "--channel", "openclaw-weixin")
|
||||
}, nil)
|
||||
if agent.AgentType == constant.AppHermesAgent {
|
||||
loginTask.AddSubTask("Restart Hermes-Agent container", func(t *task.Task) error {
|
||||
@@ -584,17 +584,26 @@ func (a AgentService) ApproveChannelPairing(req dto.AgentChannelPairingApproveRe
|
||||
return validateHermesPairingApproveResult(output, err)
|
||||
}
|
||||
if req.AccountID != "" {
|
||||
return cmd.RunDefaultBashCf(
|
||||
"docker exec %s openclaw pairing approve %s %q --account %q",
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).Run(
|
||||
"docker",
|
||||
"exec",
|
||||
install.ContainerName,
|
||||
"openclaw",
|
||||
"pairing",
|
||||
"approve",
|
||||
req.Type,
|
||||
req.PairingCode,
|
||||
"--account",
|
||||
req.AccountID,
|
||||
)
|
||||
}
|
||||
return cmd.RunDefaultBashCf(
|
||||
"docker exec %s openclaw pairing approve %s %q",
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).Run(
|
||||
"docker",
|
||||
"exec",
|
||||
install.ContainerName,
|
||||
"openclaw",
|
||||
"pairing",
|
||||
"approve",
|
||||
req.Type,
|
||||
req.PairingCode,
|
||||
)
|
||||
@@ -1289,20 +1298,40 @@ func appendPluginAllow(conf map[string]interface{}, pluginID string) {
|
||||
plugins["allow"] = append(allow, pluginID)
|
||||
}
|
||||
|
||||
func buildOpenclawPluginInstallScript(spec, pluginID string) string {
|
||||
return fmt.Sprintf(
|
||||
"set -e; workdir=%s/%s; rm -rf \"$workdir\"; mkdir -p \"$workdir\"; cd \"$workdir\"; npm pack --silent %q >/dev/null 2>&1; pkg=$(find \"$workdir\" -maxdepth 1 -type f -name '*.tgz' | head -n 1); printf '%%s\\n' \"$pkg\"; openclaw plugins install \"$pkg\" --dangerously-force-unsafe-install; rm -rf \"$workdir\"",
|
||||
openclawPluginPackageTmpDir,
|
||||
pluginID,
|
||||
spec,
|
||||
)
|
||||
func installOpenclawPlugin(mgr *cmd.CommandHelper, containerName, spec, pluginID string) error {
|
||||
workdir := path.Join(openclawPluginPackageTmpDir, pluginID)
|
||||
defer func() {
|
||||
_ = mgr.Run("docker", "exec", containerName, "rm", "-rf", workdir)
|
||||
}()
|
||||
if err := mgr.Run("docker", "exec", containerName, "rm", "-rf", workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mgr.Run("docker", "exec", containerName, "mkdir", "-p", workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mgr.Run("docker", "exec", "-w", workdir, containerName, "npm", "pack", "--silent", spec); err != nil {
|
||||
return err
|
||||
}
|
||||
pkgPath, err := mgr.RunWithStdout("docker", "exec", containerName, "find", workdir, "-maxdepth", "1", "-type", "f", "-name", "*.tgz", "-print", "-quit")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkgPath = strings.TrimSpace(pkgPath)
|
||||
if pkgPath == "" {
|
||||
return fmt.Errorf("openclaw plugin package not found")
|
||||
}
|
||||
return mgr.Run("docker", "exec", containerName, "openclaw", "plugins", "install", pkgPath, "--dangerously-force-unsafe-install")
|
||||
}
|
||||
|
||||
func buildOpenclawPluginUninstallScript(pluginID string) string {
|
||||
return fmt.Sprintf(
|
||||
"set +e; printf 'yes\\n' | openclaw plugins uninstall %s; code=$?; if [ \"$code\" -eq 137 ]; then exit 0; fi; exit \"$code\"",
|
||||
pluginID,
|
||||
func uninstallOpenclawPlugin(mgr *cmd.CommandHelper, containerName, pluginID string) error {
|
||||
_, err := mgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "printf", Args: []string{"yes\n"}},
|
||||
cmd.PipeCommand{Name: "docker", Args: []string{"exec", "-i", containerName, "openclaw", "plugins", "uninstall", pluginID}},
|
||||
)
|
||||
if err != nil && strings.Contains(err.Error(), "exit status 137") {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func resolvePluginMeta(pluginType string) (string, string, error) {
|
||||
@@ -1357,7 +1386,7 @@ func loadOpenclawPluginLatestVersion(containerName, pluginType string) (string,
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
output, err := runDockerExecWithStdout(20*time.Second, containerName, "npm", "view", spec, "version", "--json")
|
||||
output, err := cmd.RunDockerExecWithStdout(20*time.Second, containerName, "npm", "view", spec, "version", "--json")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -101,7 +102,7 @@ func countOpenclawConfiguredChannels(conf map[string]interface{}) int {
|
||||
}
|
||||
|
||||
func loadOpenclawOverviewSkillStats(containerName string) (int, error) {
|
||||
output, err := runDockerExecWithStdout(5*time.Minute, containerName, "sh", "-c", "openclaw skills list --json 2>&1")
|
||||
output, err := cmd.RunDockerExecWithStdout(5*time.Minute, containerName, "openclaw", "skills", "list", "--json")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (a AgentService) ListSkills(req dto.AgentIDReq) ([]dto.AgentSkillItem, erro
|
||||
if agent.AgentType != constant.AppOpenclaw {
|
||||
return nil, fmt.Errorf("%s does not support", agent.AgentType)
|
||||
}
|
||||
output, err := runDockerExecWithStdout(5*time.Minute, install.ContainerName, "sh", "-c", "openclaw skills list --json 2>&1")
|
||||
output, err := cmd.RunDockerExecWithStdout(5*time.Minute, install.ContainerName, "openclaw", "skills", "list", "--json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -143,7 +143,7 @@ func (a AgentService) InstallSkill(req dto.AgentSkillInstallReq) error {
|
||||
}
|
||||
installTask.AddSubTask("Install OpenClaw skill", func(t *task.Task) error {
|
||||
mgr := cmd.NewCommandMgr(cmd.WithTask(*t), cmd.WithContext(t.TaskCtx), cmd.WithTimeout(20*time.Minute))
|
||||
return mgr.Run("docker", "exec", install.ContainerName, "sh", "-c", buildOpenclawSkillInstallCommand(req.Source, req.Slug))
|
||||
return installOpenclawSkill(mgr, install.ContainerName, req.Source, req.Slug)
|
||||
}, nil)
|
||||
go func() {
|
||||
if err := installTask.Execute(); err != nil {
|
||||
@@ -205,9 +205,9 @@ func parseOpenclawSkillsList(output string) ([]dto.AgentSkillItem, error) {
|
||||
func loadOpenclawSkillSearchOutput(containerName, source, keyword string) (string, error) {
|
||||
switch source {
|
||||
case "skillhub":
|
||||
return runDockerExecWithStdout(2*time.Minute, containerName, "skillhub", "search", keyword, "--json")
|
||||
return cmd.RunDockerExecWithStdout(2*time.Minute, containerName, "skillhub", "search", keyword, "--json")
|
||||
default:
|
||||
return runDockerExecWithStdout(
|
||||
return cmd.RunDockerExecWithStdout(
|
||||
2*time.Minute,
|
||||
containerName,
|
||||
"sh",
|
||||
@@ -261,22 +261,28 @@ func parseClawhubSearchResult(output, source string) []dto.AgentSkillSearchItem
|
||||
return items
|
||||
}
|
||||
|
||||
func buildOpenclawSkillInstallCommand(source, slug string) string {
|
||||
func installOpenclawSkill(mgr *cmd.CommandHelper, containerName, source, slug string) error {
|
||||
if err := mgr.Run("docker", "exec", containerName, "mkdir", "-p", openclawManagedSkillsDir); err != nil {
|
||||
return err
|
||||
}
|
||||
switch source {
|
||||
case "clawhub-global", "clawhub-cn":
|
||||
return fmt.Sprintf(
|
||||
"mkdir -p %s && CLAWHUB_REGISTRY=%q clawhub --workdir /home/node/.openclaw --dir skills install %q",
|
||||
openclawManagedSkillsDir,
|
||||
resolveClawhubRegistry(source),
|
||||
return mgr.Run(
|
||||
"docker",
|
||||
"exec",
|
||||
"-e",
|
||||
"CLAWHUB_REGISTRY="+resolveClawhubRegistry(source),
|
||||
containerName,
|
||||
"clawhub",
|
||||
"--workdir",
|
||||
"/home/node/.openclaw",
|
||||
"--dir",
|
||||
"skills",
|
||||
"install",
|
||||
slug,
|
||||
)
|
||||
default:
|
||||
return fmt.Sprintf(
|
||||
"mkdir -p %s && skillhub --dir %s install %q",
|
||||
openclawManagedSkillsDir,
|
||||
openclawManagedSkillsDir,
|
||||
slug,
|
||||
)
|
||||
return mgr.Run("docker", "exec", containerName, "skillhub", "--dir", openclawManagedSkillsDir, "install", slug)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +296,7 @@ func resolveClawhubRegistry(source string) string {
|
||||
}
|
||||
|
||||
func getOpenclawSkillKey(containerName, name string) (string, error) {
|
||||
output, err := runDockerExecWithStdout(2*time.Minute, containerName, "sh", "-c", fmt.Sprintf("openclaw skills info %q --json 2>&1", name))
|
||||
output, err := cmd.RunDockerExecWithStdout(2*time.Minute, containerName, "openclaw", "skills", "info", name, "--json")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
|
||||
@@ -60,11 +59,6 @@ func ensureContainerRunning(containerName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDockerExecWithStdout(timeout time.Duration, containerName string, args ...string) (string, error) {
|
||||
commandArgs := append([]string{"exec", containerName}, args...)
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(timeout)).RunWithStdout("docker", commandArgs...)
|
||||
}
|
||||
|
||||
func resolveAgentAccountInput(provider, apiKey, baseURL string) (resolvedAgentAccountInput, error) {
|
||||
resolvedAPIKey := strings.TrimSpace(apiKey)
|
||||
resolvedBaseURL := strings.TrimSpace(baseURL)
|
||||
|
||||
@@ -77,7 +77,7 @@ func (u *AIToolService) LoadDetail(name string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s ollama show %s", containerName, name)
|
||||
stdout, err := cmd.RunDockerExecWithStdout(20*time.Second, containerName, "ollama", "show", name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -137,7 +137,7 @@ func (u *AIToolService) Close(name string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("docker exec %s ollama stop %s", containerName, name); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("docker", "exec", containerName, "ollama", "stop", name); err != nil {
|
||||
return fmt.Errorf("handle ollama stop %s failed, %v", name, err)
|
||||
}
|
||||
return nil
|
||||
@@ -194,7 +194,7 @@ func (u *AIToolService) Delete(req dto.ForceDelete) error {
|
||||
}
|
||||
for _, item := range ollamaList {
|
||||
if item.Status != constant.StatusDeleted {
|
||||
if err := cmd.RunDefaultBashCf("docker exec %s ollama rm %s", containerName, item.Name); err != nil && !req.ForceDelete {
|
||||
if err := cmd.NewCommandMgr().Run("docker", "exec", containerName, "ollama", "rm", item.Name); err != nil && !req.ForceDelete {
|
||||
return fmt.Errorf("handle ollama rm %s failed, %v", item.Name, err)
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func (u *AIToolService) Sync() ([]dto.OllamaModelDropList, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s ollama list", containerName)
|
||||
stdout, err := cmd.RunDockerExecWithStdout(20*time.Second, containerName, "ollama", "list")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -382,12 +382,15 @@ func LoadContainerName() (string, error) {
|
||||
}
|
||||
|
||||
func loadModelSize(name string, containerName string) (string, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s ollama list | grep %s", containerName, name)
|
||||
stdout, err := cmd.RunDockerExecWithStdout(20*time.Second, containerName, "ollama", "list")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
lines := strings.Split(stdout, "\n")
|
||||
for _, line := range lines {
|
||||
if !strings.Contains(line, name) {
|
||||
continue
|
||||
}
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 5 {
|
||||
continue
|
||||
|
||||
@@ -3,6 +3,12 @@ package service
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
@@ -15,11 +21,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/email"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"mime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AlertService struct{}
|
||||
@@ -308,12 +309,25 @@ func (a AlertService) GetDisks() ([]dto.DiskDTO, error) {
|
||||
|
||||
func executeDiskCommand() (string, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashC("df -hT -P | grep '/' | grep -v tmpfs | grep -v 'snap/core' | grep -v udev")
|
||||
stdout, err := cmdMgr.RunWithStdout("df", "-hT", "-P")
|
||||
if err != nil {
|
||||
cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
|
||||
stdout, err = cmdMgr2.RunWithStdoutBashC("df -lhT -P | grep '/' | grep -v tmpfs | grep -v 'snap/core' | grep -v udev")
|
||||
stdout, err = cmdMgr2.RunWithStdout("df", "-lhT", "-P")
|
||||
}
|
||||
return stdout, err
|
||||
if err != nil {
|
||||
return stdout, err
|
||||
}
|
||||
var lines []string
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
if !strings.Contains(line, "/") || strings.Contains(line, "tmpfs") || strings.Contains(line, "snap/core") || strings.Contains(line, "udev") {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, line)
|
||||
}
|
||||
if len(lines) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return strings.Join(lines, "\n"), nil
|
||||
}
|
||||
|
||||
func shouldExclude(fields []string, mountPoint string, excludes map[string]struct{}) bool {
|
||||
|
||||
@@ -665,7 +665,7 @@ func buildNginx(parentTask *task.Task) error {
|
||||
logStr := fmt.Sprintf("%s %s", i18n.GetMsgByKey("TaskBuild"), i18n.GetMsgByKey("Image"))
|
||||
parentTask.LogStart(logStr)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*parentTask), cmd.WithTimeout(60*time.Minute))
|
||||
if err = cmdMgr.RunBashCf("docker compose -f %s build", nginxInstall.GetComposePath()); err != nil {
|
||||
if err = cmdMgr.Run("docker", "compose", "-f", nginxInstall.GetComposePath(), "build"); err != nil {
|
||||
return err
|
||||
}
|
||||
parentTask.LogSuccess(logStr)
|
||||
@@ -768,8 +768,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
}
|
||||
}
|
||||
|
||||
command := exec.Command("/bin/bash", "-c", fmt.Sprintf("cp -rn %s/* %s || true", detailDir, install.GetPath()))
|
||||
_, _ = command.CombinedOutput()
|
||||
_ = copyAppDetailMissing(fileOp, detailDir, install.GetPath())
|
||||
if install.App.Key == constant.AppOpenresty {
|
||||
installBuildDir := path.Join(install.GetPath(), "build")
|
||||
detailBuildDir := path.Join(detailDir, "build")
|
||||
@@ -1129,7 +1128,7 @@ func runScript(task *task.Task, appInstall *model.AppInstall, operate string) er
|
||||
task.LogStart(logStr)
|
||||
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute), cmd.WithWorkDir(workDir))
|
||||
if err := cmdMgr.RunBashC(scriptPath); err != nil {
|
||||
if err := cmdMgr.Run("bash", scriptPath); err != nil {
|
||||
task.LogFailedWithErr(logStr, err)
|
||||
return err
|
||||
}
|
||||
@@ -1935,6 +1934,39 @@ func isHostModel(dockerCompose string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func copyAppDetailMissing(fileOp files.FileOp, srcDir, dstDir string) error {
|
||||
entries, err := os.ReadDir(srcDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if strings.HasPrefix(entry.Name(), ".") {
|
||||
continue
|
||||
}
|
||||
srcPath := path.Join(srcDir, entry.Name())
|
||||
dstPath := path.Join(dstDir, entry.Name())
|
||||
if !fileOp.Stat(dstPath) {
|
||||
if entry.IsDir() {
|
||||
if err := fileOp.CopyDir(srcPath, dstDir); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := fileOp.CopyFile(srcPath, dstDir); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
if err := copyAppDetailMissing(fileOp, srcPath, dstPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRestartPolicy(yml string) string {
|
||||
var project docker.ComposeProject
|
||||
if err := yaml.Unmarshal([]byte(yml), &project); err != nil {
|
||||
|
||||
@@ -97,7 +97,7 @@ func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, recordID
|
||||
}
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashCf("docker exec %s redis-cli -a %s --no-auth-warning save", redisInfo.ContainerName, redisInfo.Password); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("docker", "exec", redisInfo.ContainerName, "redis-cli", "-a", redisInfo.Password, "--no-auth-warning", "save"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -109,13 +109,13 @@ func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, recordID
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(fileName, ".aof") {
|
||||
if err := cmd.RunDefaultBashCf("docker cp %s:/data/appendonly.aof %s/%s", redisInfo.ContainerName, backupDir, fileName); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("docker", "cp", redisInfo.ContainerName+":/data/appendonly.aof", path.Join(backupDir, fileName)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashCf("docker cp %s:/data/dump.rdb %s/%s", redisInfo.ContainerName, backupDir, fileName); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("docker", "cp", redisInfo.ContainerName+":/data/dump.rdb", path.Join(backupDir, fileName)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -178,7 +178,7 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
|
||||
if err = fileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), GetOpenrestyDir(SitesRootDir), ""); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("docker", "exec", "-i", nginxInfo.ContainerName, "nginx", "-s", "reload"); err != nil {
|
||||
return err
|
||||
}
|
||||
oldWebsite.ID = website.ID
|
||||
|
||||
@@ -86,8 +86,9 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
|
||||
baseInfo.IsActive = false
|
||||
}
|
||||
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
|
||||
if baseInfo.IsActive {
|
||||
version, err := cmd.RunDefaultWithStdoutBashC("clamdscan --version")
|
||||
version, err := cmdMgr.RunWithStdout("clamdscan", "--version")
|
||||
if err == nil {
|
||||
if strings.Contains(version, "/") {
|
||||
baseInfo.Version = strings.TrimPrefix(strings.Split(version, "/")[0], "ClamAV ")
|
||||
@@ -99,7 +100,7 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
|
||||
_ = clam.CheckWithStopAll(false, clamRepo)
|
||||
}
|
||||
if baseInfo.FreshIsActive {
|
||||
version, err := cmd.RunDefaultWithStdoutBashC("freshclam --version")
|
||||
version, err := cmdMgr.RunWithStdout("freshclam", "--version")
|
||||
if err == nil {
|
||||
if strings.Contains(version, "/") {
|
||||
baseInfo.FreshVersion = strings.TrimPrefix(strings.Split(version, "/")[0], "ClamAV ")
|
||||
|
||||
@@ -1167,7 +1167,7 @@ func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error
|
||||
|
||||
func (u *ContainerService) LoadUsers(req dto.OperationWithName) []string {
|
||||
var users []string
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("docker", "exec", req.Name, "cat", "/etc/passwd")
|
||||
std, err := cmd.RunDockerExecWithStdout(20*time.Second, req.Name, "cat", "/etc/passwd")
|
||||
if err != nil {
|
||||
return users
|
||||
}
|
||||
@@ -1440,7 +1440,7 @@ func (u *ContainerService) DownloadContainerFile(req dto.ContainerFileReq) (io.R
|
||||
fileName = "container-file"
|
||||
}
|
||||
if stat.Mode.IsDir() {
|
||||
if _, err := runContainerCommand(cli, req.ContainerID, []string{"sh", "-c", "command -v tar >/dev/null 2>&1"}); err != nil {
|
||||
if _, err := runContainerCommand(cli, req.ContainerID, []string{"tar", "--help"}); err != nil {
|
||||
_ = cli.Close()
|
||||
return nil, "", "", fmt.Errorf("tar command not found in container")
|
||||
}
|
||||
@@ -1620,9 +1620,8 @@ func toContainerFileInfo(filePath string, stat container.PathStat, isDir bool) d
|
||||
}
|
||||
|
||||
func isContainerDir(cli *client.Client, containerID, targetPath string) (bool, error) {
|
||||
_, err := runContainerCommand(cli, containerID, []string{
|
||||
"sh", "-c", "[ -d \"$1\" ]", "sh", targetPath,
|
||||
})
|
||||
checkPath := strings.TrimSuffix(targetPath, "/") + "/."
|
||||
_, err := runContainerCommand(cli, containerID, []string{"ls", "-d", "--", checkPath})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime t
|
||||
|
||||
func backupLogFile(dstFilePath, websiteLogDir string, fileOp files.FileOp) error {
|
||||
cmdMgr := cmd.NewCommandMgr()
|
||||
if err := cmdMgr.RunBashCf("tar -czf %s -C %s %s", dstFilePath, websiteLogDir, strings.Join([]string{"access.log", "error.log"}, " ")); err != nil {
|
||||
if err := cmdMgr.Run("tar", "-czf", dstFilePath, "-C", websiteLogDir, "access.log", "error.log"); err != nil {
|
||||
dstDir := pathUtils.Dir(dstFilePath)
|
||||
if err = fileOp.Copy(pathUtils.Join(websiteLogDir, "access.log"), dstDir); err != nil {
|
||||
return err
|
||||
@@ -399,7 +399,7 @@ func backupLogFile(dstFilePath, websiteLogDir string, fileOp files.FileOp) error
|
||||
if err = fileOp.Copy(pathUtils.Join(websiteLogDir, "error.log"), dstDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = cmdMgr.RunBashCf("tar -czf %s -C %s %s", dstFilePath, dstDir, strings.Join([]string{"access.log", "error.log"}, " ")); err != nil {
|
||||
if err = cmdMgr.Run("tar", "-czf", dstFilePath, "-C", dstDir, "access.log", "error.log"); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = fileOp.DeleteFile(pathUtils.Join(dstDir, "access.log"))
|
||||
|
||||
@@ -60,7 +60,9 @@ func (u *DashboardService) Restart(operation string) error {
|
||||
case "system":
|
||||
{
|
||||
go func() {
|
||||
if err := cmd.RunDefaultBashCf("%s reboot", cmd.SudoHandleCmd()); err != nil {
|
||||
cmdMgr := cmd.NewCommandMgr()
|
||||
err := cmdMgr.RunWithOptionalSudo("reboot")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("handle reboot failed, %v", err)
|
||||
}
|
||||
}()
|
||||
@@ -429,11 +431,17 @@ type diskInfo struct {
|
||||
func loadDiskInfo() []dto.DiskInfo {
|
||||
var datas []dto.DiskInfo
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second))
|
||||
format := `awk 'NR>1 && !/tmpfs|snap\/core|udev/ {printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7}'`
|
||||
stdout, err := cmdMgr.RunWithStdout("bash", "-c", `timeout 2 df -hT -P | `+format)
|
||||
format := `NR>1 && !/tmpfs|snap\/core|udev/ {printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7}`
|
||||
stdout, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "df", Args: []string{"-hT", "-P"}},
|
||||
cmd.PipeCommand{Name: "awk", Args: []string{format}},
|
||||
)
|
||||
if err != nil {
|
||||
cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
|
||||
stdout, err = cmdMgr2.RunWithStdout("bash", "-c", `timeout 1 df -lhT -P | `+format)
|
||||
stdout, err = cmdMgr2.RunPipe(
|
||||
cmd.PipeCommand{Name: "df", Args: []string{"-lhT", "-P"}},
|
||||
cmd.PipeCommand{Name: "awk", Args: []string{format}},
|
||||
)
|
||||
if err != nil {
|
||||
return datas
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func (u *DeviceService) LoadBaseInfo() (dto.DeviceBaseInfo, error) {
|
||||
}
|
||||
|
||||
func (u *DeviceService) LoadTimeZone() ([]string, error) {
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Minute)).RunWithStdoutBashC("timedatectl list-timezones")
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdout("timedatectl", "list-timezones")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
@@ -223,7 +223,9 @@ func (u *DeviceService) UpdatePasswd(req dto.ChangePasswd) error {
|
||||
if cmd.CheckIllegal(req.User, req.Passwd) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("%s echo '%s:%s' | %s chpasswd", cmd.SudoHandleCmd(), req.User, req.Passwd, cmd.SudoHandleCmd()); err != nil {
|
||||
cmdItem := cmd.ExecCommandWithOptionalSudo("chpasswd")
|
||||
cmdItem.Stdin = strings.NewReader(req.User + ":" + req.Passwd)
|
||||
if err := cmdItem.Run(); err != nil {
|
||||
if strings.Contains(err.Error(), "does not exist") {
|
||||
return buserr.New("ErrNotExistUser")
|
||||
}
|
||||
@@ -393,7 +395,7 @@ func loadHosts() []dto.HostHelper {
|
||||
}
|
||||
|
||||
func loadHostname() string {
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("hostname")
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)).RunWithStdout("hostname")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
@@ -401,7 +403,7 @@ func loadHostname() string {
|
||||
}
|
||||
|
||||
func loadUser() string {
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("whoami")
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)).RunWithStdout("whoami")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
@@ -410,7 +412,8 @@ func loadUser() string {
|
||||
|
||||
func loadSwap() []dto.SwapHelper {
|
||||
var data []dto.SwapHelper
|
||||
std, err := cmd.RunDefaultWithStdoutBashCf("%s swapon --summary", cmd.SudoHandleCmd())
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
|
||||
std, err := cmdMgr.RunWithOptionalSudoAndStdout("swapon", "--summary")
|
||||
if err != nil {
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ func NewIDiskService() IDiskService {
|
||||
|
||||
func (s *DiskService) GetCompleteDiskInfo() (*response.CompleteDiskInfo, error) {
|
||||
var diskInfos []response.DiskBasicInfo
|
||||
output, err := cmd.RunDefaultWithStdoutBashC("lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
|
||||
output, err := cmdMgr.RunWithStdout("lsblk", "-J", "-o", "NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
if err == nil {
|
||||
diskInfos, err = parseLsblkJsonOutput(output)
|
||||
if err == nil {
|
||||
@@ -38,7 +39,7 @@ func (s *DiskService) GetCompleteDiskInfo() (*response.CompleteDiskInfo, error)
|
||||
return &result, nil
|
||||
}
|
||||
}
|
||||
output, err = cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
output, err = cmdMgr.RunWithStdout("lsblk", "-P", "-o", "NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to run lsblk command: %v", err)
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
||||
@@ -386,10 +388,14 @@ func getParentDevice(device string) string {
|
||||
}
|
||||
|
||||
func getDiskUsageInfo(device string) (size, used, avail string, usePercent int, err error) {
|
||||
output, err := cmd.RunDefaultWithStdoutBashC(fmt.Sprintf("df -h %s | tail -1", device))
|
||||
output, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("df", "-h", device)
|
||||
if err != nil {
|
||||
return "", "", "", 0, nil
|
||||
}
|
||||
lines := strings.Split(strings.TrimSpace(output), "\n")
|
||||
if len(lines) > 1 {
|
||||
output = lines[len(lines)-1]
|
||||
}
|
||||
|
||||
fields := strings.Fields(output)
|
||||
if len(fields) >= 5 {
|
||||
@@ -515,7 +521,7 @@ func removeFromFstab(mountPoint string) error {
|
||||
}
|
||||
|
||||
func getFilesystemType(device string) (string, error) {
|
||||
output, err := cmd.RunDefaultWithStdoutBashC(fmt.Sprintf("blkid -o value -s TYPE %s", device))
|
||||
output, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("blkid", "-o", "value", "-s", "TYPE", device)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -575,7 +581,7 @@ func parseSizeToBytes(sizeStr string) int64 {
|
||||
}
|
||||
|
||||
func getDeviceUUID(device string) (string, error) {
|
||||
output, err := cmd.RunDefaultWithStdoutBashC(fmt.Sprintf("blkid -s UUID -o value %s", device))
|
||||
output, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("blkid", "-s", "UUID", "-o", "value", device)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
@@ -89,8 +90,8 @@ func (u *DockerService) LoadDockerConf() (*dto.DaemonJsonConf, error) {
|
||||
data.Version = itemVersion.Version
|
||||
}
|
||||
data.IsSwarm = false
|
||||
stdout2, _ := cmd.RunDefaultWithStdoutBashC("docker info | grep Swarm")
|
||||
if string(stdout2) == " Swarm: active\n" {
|
||||
stdout2, _ := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("docker", "info")
|
||||
if strings.Contains(stdout2, "Swarm: active") {
|
||||
data.IsSwarm = true
|
||||
}
|
||||
if _, err := os.Stat(constant.DaemonJsonPath); err != nil {
|
||||
@@ -423,7 +424,7 @@ func validateDockerConfig() error {
|
||||
if !cmd.Which("dockerd") {
|
||||
return nil
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("dockerd --validate")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("dockerd", "--validate")
|
||||
if strings.Contains(stdout, "unknown flag: --validate") {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (h *HostToolService) GetToolStatus(req request.HostToolReq) (*response.Host
|
||||
supervisorConfig.ServiceName = serviceNameSet.Value
|
||||
}
|
||||
|
||||
versionRes, _ := cmd.RunDefaultWithStdoutBashC("supervisord -v")
|
||||
versionRes, _ := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("supervisord", "-v")
|
||||
supervisorConfig.Version = strings.TrimSuffix(versionRes, "\n")
|
||||
_, ctlRrr := exec.LookPath("supervisorctl")
|
||||
supervisorConfig.CtlExist = ctlRrr == nil
|
||||
@@ -550,8 +550,8 @@ func operateSupervisorCtl(operate, name, group, includeDir, containerName string
|
||||
err error
|
||||
)
|
||||
if containerName != "" {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(30 * time.Second))
|
||||
output, err = cmdMgr.RunWithStdoutBashCf("docker exec %s supervisorctl %s", containerName, strings.Join(processNames, " "))
|
||||
args := append([]string{"supervisorctl"}, processNames...)
|
||||
output, err = cmd.RunDockerExecWithStdout(30*time.Second, containerName, args...)
|
||||
} else {
|
||||
var out []byte
|
||||
out, err = exec.Command("supervisorctl", processNames...).Output()
|
||||
@@ -593,8 +593,8 @@ func getProcessStatus(config *response.SupervisorProcessConfig, containerName st
|
||||
)
|
||||
processNames = append(processNames, getProcessName(config.Name, config.Numprocs)...)
|
||||
if containerName != "" {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(3 * time.Second))
|
||||
output, err = cmdMgr.RunWithStdoutBashCf("docker exec %s supervisorctl %s", containerName, strings.Join(processNames, " "))
|
||||
args := append([]string{"supervisorctl"}, processNames...)
|
||||
output, err = cmd.RunDockerExecWithStdout(3*time.Second, containerName, args...)
|
||||
} else {
|
||||
var out []byte
|
||||
out, err = exec.Command("supervisorctl", processNames...).Output()
|
||||
|
||||
@@ -359,10 +359,10 @@ func loadBindNumber(chain string) int {
|
||||
}
|
||||
|
||||
func initPreRules() error {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.IoRuleIn); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-i", "lo", "-j", "ACCEPT", "-m", "comment", "--comment", "Loopback Whitelist"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT", "-m", "comment", "--comment", "ESTABLISHED Whitelist"); err != nil {
|
||||
return err
|
||||
}
|
||||
panelPort := LoadPanelPort()
|
||||
@@ -371,17 +371,17 @@ func initPreRules() error {
|
||||
}
|
||||
ports := []string{"80", "443", panelPort, loadSSHPort()}
|
||||
for _, item := range ports {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", item)); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-p", "tcp", "-m", "tcp", "--dport", item, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p udp -m udp --dport 443 -j ACCEPT"); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "udp", "-m", "udp", "--dport", "443", "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllTcp); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "tcp", "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllUdp); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "udp", "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -241,7 +241,7 @@ func (n NginxService) Build(req request.NginxBuildReq) error {
|
||||
}
|
||||
buildTask.AddSubTaskWithOps("", func(t *task.Task) error {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*buildTask), cmd.WithTimeout(120*time.Minute))
|
||||
if err = cmdMgr.RunBashCf("docker compose -f %s build", nginxInstall.GetComposePath()); err != nil {
|
||||
if err = cmdMgr.Run("docker", "compose", "-f", nginxInstall.GetComposePath(), "build"); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = compose.DownAndUp(nginxInstall.GetComposePath())
|
||||
|
||||
@@ -240,16 +240,10 @@ func getNginxParamsFromStaticFile(scope dto.NginxKey, newParams []dto.NginxParam
|
||||
|
||||
func opNginx(containerName, operate string) error {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
|
||||
cmdStr := fmt.Sprintf("docker exec -i %s nginx ", containerName)
|
||||
if operate == constant.NginxCheck {
|
||||
cmdStr = cmdStr + "-t"
|
||||
} else {
|
||||
cmdStr = cmdStr + "-s reload"
|
||||
return cmdMgr.Run("docker", "exec", "-i", containerName, "nginx", "-t")
|
||||
}
|
||||
if err := cmdMgr.RunBashC(cmdStr); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return cmdMgr.Run("docker", "exec", "-i", containerName, "nginx", "-s", "reload")
|
||||
}
|
||||
|
||||
func nginxCheckAndReload(oldContent string, filePath string, containerName string) error {
|
||||
|
||||
@@ -630,11 +630,14 @@ func (r *RuntimeService) OperateNodeModules(req request.NodeModuleOperateReq) er
|
||||
return err
|
||||
}
|
||||
operation := getOperation(req.Operate, req.PkgManager)
|
||||
execScript := fmt.Sprintf("%s %s %s", req.PkgManager, operation, req.Module)
|
||||
execArgs := []string{"exec", "-i", containerName, req.PkgManager, operation}
|
||||
if strings.TrimSpace(req.Module) != "" {
|
||||
execArgs = append(execArgs, req.Module)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute)
|
||||
defer cancel()
|
||||
installCmd := exec.CommandContext(ctx, "docker", "exec", "-i", containerName, "bash", "-c", execScript)
|
||||
installCmd := exec.CommandContext(ctx, "docker", execArgs...)
|
||||
output, err := installCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute command: %s, error: %w", string(output), err)
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
fileUtils "github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
@@ -303,12 +302,20 @@ func loadAppImage(list []dto.DataTree) []dto.DataTree {
|
||||
if list[i].IsLocal {
|
||||
appPath = path.Join(global.Dir.AppDir, "local", strings.TrimPrefix(list[i].Key, "local"), list[i].Name)
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("cat %s | grep image: ", path.Join(appPath, "docker-compose.yml"))
|
||||
composePath := path.Join(appPath, "docker-compose.yml")
|
||||
content, err := os.ReadFile(composePath)
|
||||
if err != nil {
|
||||
list[i].Children = append(list[i].Children, itemAppImage)
|
||||
continue
|
||||
}
|
||||
itemAppImage.Name = strings.ReplaceAll(strings.ReplaceAll(strings.TrimSpace(stdout), "\n", ""), "image: ", "")
|
||||
for _, line := range strings.Split(string(content), "\n") {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(trimmed, "image:") {
|
||||
continue
|
||||
}
|
||||
itemAppImage.Name = strings.TrimSpace(strings.TrimPrefix(trimmed, "image:"))
|
||||
break
|
||||
}
|
||||
for _, imageItem := range imageList {
|
||||
for _, tag := range imageItem.RepoTags {
|
||||
if tag == itemAppImage.Name {
|
||||
|
||||
@@ -405,7 +405,12 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
|
||||
if len(imageList) != 0 {
|
||||
snap.Task.Log(strings.Join(imageList, " "))
|
||||
snap.Task.Logf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz"))
|
||||
if err := cmd.RunDefaultBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz")); err != nil {
|
||||
outputPath := path.Join(targetDir, "images.tar.gz")
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithOutputFile(outputPath))
|
||||
if _, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "docker", Args: append([]string{"save"}, imageList...)},
|
||||
cmd.PipeCommand{Name: "gzip", Args: []string{"-c"}},
|
||||
); err != nil {
|
||||
snap.Task.LogFailedWithErr(i18n.GetMsgByKey("SnapDockerSave"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -376,7 +377,15 @@ func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log(i18n.GetMsgByKey("RecoverAppEmpty"))
|
||||
return nil
|
||||
}
|
||||
if err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunBashCf("docker load < %s", path.Join(src, "images.tar.gz")); err != nil {
|
||||
imageFile, err := os.Open(path.Join(src, "images.tar.gz"))
|
||||
if err != nil {
|
||||
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverAppImage"), err)
|
||||
return fmt.Errorf("docker load images failed, %v", err)
|
||||
}
|
||||
defer func() { _ = imageFile.Close() }()
|
||||
loadCmd := exec.Command("docker", "load")
|
||||
loadCmd.Stdin = imageFile
|
||||
if err := loadCmd.Run(); err != nil {
|
||||
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverAppImage"), err)
|
||||
return fmt.Errorf("docker load images failed, %v", err)
|
||||
}
|
||||
@@ -457,8 +466,7 @@ func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
|
||||
if _, err := os.Stat(pathItem); err != nil {
|
||||
continue
|
||||
}
|
||||
upCmd := fmt.Sprintf("docker compose -f %s up -d", pathItem)
|
||||
if err := cmd.RunDefaultBashC(upCmd); err != nil {
|
||||
if err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).Run("docker", "compose", "-f", pathItem, "up", "-d"); err != nil {
|
||||
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverCompose"), err)
|
||||
continue
|
||||
}
|
||||
|
||||
+47
-27
@@ -586,12 +586,12 @@ func (u *SSHService) LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (int64, []d
|
||||
}
|
||||
fileList = sortFileList(fileList)
|
||||
|
||||
command := ""
|
||||
filter := ""
|
||||
if len(req.Info) != 0 {
|
||||
if cmd.CheckIllegal(req.Info) {
|
||||
return 0, data, buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
command = fmt.Sprintf(" | grep '%s'", req.Info)
|
||||
filter = req.Info
|
||||
}
|
||||
|
||||
showCountFrom := (req.Page - 1) * req.PageSize
|
||||
@@ -599,28 +599,7 @@ func (u *SSHService) LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (int64, []d
|
||||
nyc, _ := time.LoadLocation(common.LoadTimeZoneByCmd())
|
||||
itemFailed, itemTotal := 0, 0
|
||||
for _, file := range fileList {
|
||||
commandItem := ""
|
||||
if strings.HasPrefix(path.Base(file.Name), "secure") {
|
||||
switch req.Status {
|
||||
case constant.StatusSuccess:
|
||||
commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command)
|
||||
case constant.StatusFailed:
|
||||
commandItem = fmt.Sprintf("cat %s | grep -a 'Failed password for' %s", file.Name, command)
|
||||
default:
|
||||
commandItem = fmt.Sprintf("cat %s | grep -aE '(Failed password for|Accepted)' %s", file.Name, command)
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(path.Base(file.Name), "auth.log") {
|
||||
switch req.Status {
|
||||
case constant.StatusSuccess:
|
||||
commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command)
|
||||
case constant.StatusFailed:
|
||||
commandItem = fmt.Sprintf("cat %s | grep -aE 'Failed password for|Connection closed by authenticating user' %s", file.Name, command)
|
||||
default:
|
||||
commandItem = fmt.Sprintf("cat %s | grep -aE \"(Failed password for|Connection closed by authenticating user|Accepted)\" %s", file.Name, command)
|
||||
}
|
||||
}
|
||||
dataItem, successCount, failedCount := loadSSHData(ctx, commandItem, showCountFrom, showCountTo, file.Year, nyc)
|
||||
dataItem, successCount, failedCount := loadSSHData(ctx, file.Name, path.Base(file.Name), req.Status, filter, showCountFrom, showCountTo, file.Year, nyc)
|
||||
itemFailed += failedCount
|
||||
itemTotal += successCount + failedCount
|
||||
showCountFrom = showCountFrom - (successCount + failedCount)
|
||||
@@ -1124,7 +1103,7 @@ func isSSHConfigPathAllowed(fileName string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func loadSSHData(ctx *gin.Context, command string, showCountFrom, showCountTo, currentYear int, nyc *time.Location) ([]dto.SSHHistory, int, int) {
|
||||
func loadSSHData(ctx *gin.Context, filePath, fileName, status, filter string, showCountFrom, showCountTo, currentYear int, nyc *time.Location) ([]dto.SSHHistory, int, int) {
|
||||
var (
|
||||
datas []dto.SSHHistory
|
||||
successCount int
|
||||
@@ -1134,12 +1113,15 @@ func loadSSHData(ctx *gin.Context, command string, showCountFrom, showCountTo, c
|
||||
if err != nil {
|
||||
return datas, 0, 0
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC(command)
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return datas, 0, 0
|
||||
}
|
||||
lines := strings.Split(stdout, "\n")
|
||||
lines := strings.Split(string(content), "\n")
|
||||
for i := len(lines) - 1; i >= 0; i-- {
|
||||
if !matchSSHLogLine(fileName, status, filter, lines[i]) {
|
||||
continue
|
||||
}
|
||||
var itemData dto.SSHHistory
|
||||
switch {
|
||||
case strings.Contains(lines[i], "Failed password for"):
|
||||
@@ -1177,6 +1159,44 @@ func loadSSHData(ctx *gin.Context, command string, showCountFrom, showCountTo, c
|
||||
return datas, successCount, failedCount
|
||||
}
|
||||
|
||||
func matchSSHLogLine(fileName, status, filter, line string) bool {
|
||||
if filter != "" && !strings.Contains(line, filter) {
|
||||
return false
|
||||
}
|
||||
containsFailed := strings.Contains(line, "Failed password for")
|
||||
containsClosed := strings.Contains(line, "Connection closed by authenticating user")
|
||||
containsAccepted := strings.Contains(line, "Accepted ")
|
||||
switch {
|
||||
case strings.HasPrefix(fileName, "secure"):
|
||||
switch status {
|
||||
case constant.StatusSuccess:
|
||||
return containsAccepted
|
||||
case constant.StatusFailed:
|
||||
return containsFailed
|
||||
default:
|
||||
return containsFailed || containsAccepted
|
||||
}
|
||||
case strings.HasPrefix(fileName, "auth.log"):
|
||||
switch status {
|
||||
case constant.StatusSuccess:
|
||||
return containsAccepted
|
||||
case constant.StatusFailed:
|
||||
return containsFailed || containsClosed
|
||||
default:
|
||||
return containsFailed || containsClosed || containsAccepted
|
||||
}
|
||||
default:
|
||||
switch status {
|
||||
case constant.StatusSuccess:
|
||||
return containsAccepted
|
||||
case constant.StatusFailed:
|
||||
return containsFailed || containsClosed
|
||||
default:
|
||||
return containsFailed || containsClosed || containsAccepted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadSuccessDatas(line string) dto.SSHHistory {
|
||||
var data dto.SSHHistory
|
||||
parts := strings.Fields(line)
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ssl"
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
@@ -378,8 +377,7 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) (*model.Website
|
||||
workDir = websiteSSL.Dir
|
||||
}
|
||||
logger.Println(i18n.GetMsgByKey("ExecShellStart"))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(30*time.Minute), cmd.WithLogger(logger), cmd.WithWorkDir(workDir))
|
||||
if err = cmdMgr.RunBashC(websiteSSL.Shell); err != nil {
|
||||
if err = runShellScriptFile(workDir, websiteSSL.Shell, logger); err != nil {
|
||||
logger.Println(i18n.GetMsgWithMap("ErrExecShell", map[string]interface{}{"err": err.Error()}))
|
||||
} else {
|
||||
logger.Println(i18n.GetMsgByKey("ExecShellSuccess"))
|
||||
|
||||
@@ -402,8 +402,7 @@ func (w WebsiteSSLService) obtainSSL(id uint, autoRenew bool) error {
|
||||
workDir = websiteSSL.Dir
|
||||
}
|
||||
printSSLLog(logger, "ExecShellStart", nil)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(30*time.Minute), cmd.WithLogger(logger), cmd.WithWorkDir(workDir))
|
||||
if err = cmdMgr.RunBashC(websiteSSL.Shell); err != nil {
|
||||
if err = runShellScriptFile(workDir, websiteSSL.Shell, logger); err != nil {
|
||||
printSSLLog(logger, "ErrExecShell", map[string]interface{}{"err": err.Error()})
|
||||
} else {
|
||||
printSSLLog(logger, "ExecShellSuccess", nil)
|
||||
@@ -447,6 +446,23 @@ func (w WebsiteSSLService) obtainSSL(id uint, autoRenew bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runShellScriptFile(workDir, shell string, logger *log.Logger) error {
|
||||
file, err := os.CreateTemp("", "1panel-shell-*.sh")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = os.Remove(file.Name()) }()
|
||||
if _, err := file.WriteString(shell); err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(30*time.Minute), cmd.WithLogger(logger), cmd.WithWorkDir(workDir))
|
||||
return cmdMgr.Run("bash", file.Name())
|
||||
}
|
||||
|
||||
func handleError(websiteSSL *model.WebsiteSSL, err error) {
|
||||
if websiteSSL.Status == constant.SSLInit || websiteSSL.Status == constant.SSLError {
|
||||
websiteSSL.Status = constant.StatusError
|
||||
|
||||
@@ -1221,7 +1221,7 @@ func checkIsLinkApp(website model.Website) bool {
|
||||
|
||||
func chownRootDir(path string) error {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
|
||||
if err := cmdMgr.RunBashCf(`chown -R 1000:1000 "%s"`, path); err != nil {
|
||||
if err := cmdMgr.Run("chown", "-R", "1000:1000", path); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -71,7 +71,7 @@ func Init() {
|
||||
global.LOG.Errorf("find 1panel service port failed")
|
||||
return
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", panelPort)); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-p", "tcp", "-m", "tcp", "--dport", panelPort, "-j", "ACCEPT"); err != nil {
|
||||
global.LOG.Errorf("add port accept rule %v failed, err: %v", panelPort, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package hook
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/alert_push"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
)
|
||||
|
||||
@@ -140,11 +140,10 @@ func loadLocalDir() {
|
||||
}
|
||||
|
||||
func initDockerConf() {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("which docker")
|
||||
dockerPath, err := exec.LookPath("docker")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dockerPath := stdout
|
||||
if strings.Contains(dockerPath, "snap") {
|
||||
constant.DaemonJsonPath = "/var/snap/docker/current/config/daemon.json"
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func initLang() {
|
||||
downloadLangFromRemote(fileOp)
|
||||
return
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("cp -r %s %s", path.Join(tmpPath, "lang"), "/usr/local/bin/"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("cp", "-r", "--", path.Join(tmpPath, "lang"), "/usr/local/bin/"); err != nil {
|
||||
global.LOG.Errorf("load lang from package failed, %v", err)
|
||||
return
|
||||
}
|
||||
@@ -73,7 +73,11 @@ func initLang() {
|
||||
downloadGeoFromRemote(fileOp, geoPath)
|
||||
return
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("mkdir %s && cp %s %s/", path.Dir(geoPath), path.Join(tmpPath, "GeoIP.mmdb"), path.Dir(geoPath)); err != nil {
|
||||
if err := os.MkdirAll(path.Dir(geoPath), os.ModePerm); err != nil {
|
||||
global.LOG.Errorf("load geo ip from package failed, %v", err)
|
||||
return
|
||||
}
|
||||
if err := cmd.NewCommandMgr().Run("cp", "--", path.Join(tmpPath, "GeoIP.mmdb"), path.Dir(geoPath)+"/"); err != nil {
|
||||
global.LOG.Errorf("load geo ip from package failed, %v", err)
|
||||
return
|
||||
}
|
||||
@@ -114,7 +118,7 @@ func downloadLangFromRemote(fileOp files.FileOp) {
|
||||
global.LOG.Error("download lang.tar.gz failed, no such file")
|
||||
return
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("tar zxvfC %s %s", "/usr/local/bin/lang.tar.gz", "/usr/local/bin/"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("tar", "zxvfC", "/usr/local/bin/lang.tar.gz", "/usr/local/bin/"); err != nil {
|
||||
global.LOG.Errorf("decompress lang.tar.gz failed, %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -29,7 +30,7 @@ func Certificate() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
masterProxyID := c.Request.Header.Get("Proxy-Id")
|
||||
proxyID, err := cmd.RunDefaultWithStdoutBashC("cat /etc/1panel/.nodeProxyID")
|
||||
proxyID, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("cat", "/etc/1panel/.nodeProxyID")
|
||||
if err == nil && len(proxyID) != 0 && strings.TrimSpace(proxyID) != strings.TrimSpace(masterProxyID) {
|
||||
helper.InternalServer(c, fmt.Errorf("err proxy id"))
|
||||
return
|
||||
|
||||
@@ -24,7 +24,7 @@ func New() (bool, NvidiaSMI) {
|
||||
|
||||
func (n NvidiaSMI) LoadGpuInfo() (*common.GpuInfo, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
itemData, err := cmdMgr.RunWithStdoutBashC("nvidia-smi -q -x")
|
||||
itemData, err := cmdMgr.RunWithStdout("nvidia-smi", "-q", "-x")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling nvidia-smi failed, %v", err)
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ func (x XpuSMI) loadDeviceData(device Device, wg *sync.WaitGroup, res *[]XPUSimp
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
go func() {
|
||||
defer wgCmd.Done()
|
||||
xpuData, xpuErr = cmdMgr.RunWithStdoutBashCf("xpu-smi discovery -d %d -j", device.DeviceID)
|
||||
xpuData, xpuErr = cmdMgr.RunWithStdout("xpu-smi", "discovery", "-d", strconv.Itoa(device.DeviceID), "-j")
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wgCmd.Done()
|
||||
statsData, statsErr = cmdMgr.RunWithStdoutBashCf("xpu-smi stats -d %d -j", device.DeviceID)
|
||||
statsData, statsErr = cmdMgr.RunWithStdout("xpu-smi", "stats", "-d", strconv.Itoa(device.DeviceID), "-j")
|
||||
}()
|
||||
|
||||
wgCmd.Wait()
|
||||
@@ -93,7 +93,7 @@ func (x XpuSMI) loadDeviceData(device Device, wg *sync.WaitGroup, res *[]XPUSimp
|
||||
|
||||
func (x XpuSMI) LoadDashData() ([]XPUSimpleInfo, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
data, err := cmdMgr.RunWithStdoutBashC("xpu-smi discovery -j")
|
||||
data, err := cmdMgr.RunWithStdout("xpu-smi", "discovery", "-j")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling xpu-smi failed, %v", err)
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func (x XpuSMI) LoadDashData() ([]XPUSimpleInfo, error) {
|
||||
|
||||
func (x XpuSMI) LoadGpuInfo() (*XpuInfo, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
data, err := cmdMgr.RunWithStdoutBashC("xpu-smi discovery -j")
|
||||
data, err := cmdMgr.RunWithStdout("xpu-smi", "discovery", "-j")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling xpu-smi failed, %v", err)
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (x XpuSMI) LoadGpuInfo() (*XpuInfo, error) {
|
||||
|
||||
wg.Wait()
|
||||
|
||||
processData, err := cmdMgr.RunWithStdoutBashC("xpu-smi ps -j")
|
||||
processData, err := cmdMgr.RunWithStdout("xpu-smi", "ps", "-j")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling xpu-smi ps failed, %s", err)
|
||||
}
|
||||
@@ -194,12 +194,12 @@ func (x XpuSMI) loadDeviceInfo(device Device, wg *sync.WaitGroup, res *XpuInfo,
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
go func() {
|
||||
defer wgCmd.Done()
|
||||
xpuData, xpuErr = cmdMgr.RunWithStdoutBashCf("xpu-smi discovery -d %d -j", device.DeviceID)
|
||||
xpuData, xpuErr = cmdMgr.RunWithStdout("xpu-smi", "discovery", "-d", strconv.Itoa(device.DeviceID), "-j")
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wgCmd.Done()
|
||||
statsData, statsErr = cmdMgr.RunWithStdoutBashCf("xpu-smi stats -d %d -j", device.DeviceID)
|
||||
statsData, statsErr = cmdMgr.RunWithStdout("xpu-smi", "stats", "-d", strconv.Itoa(device.DeviceID), "-j")
|
||||
}()
|
||||
|
||||
wgCmd.Wait()
|
||||
|
||||
@@ -34,7 +34,7 @@ func AddScanTask(taskItem *task.Task, clam model.Clam, timeNow string) {
|
||||
}
|
||||
taskItem.Logf("clamdscan --fdpass %s %s", strategy, clam.Path)
|
||||
mgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(time.Duration(clam.Timeout)*time.Second), cmd.WithTask(*taskItem))
|
||||
if err := mgr.RunBashCf("clamdscan --fdpass %s %s", strategy, clam.Path); err != nil {
|
||||
if err := mgr.Run("clamdscan", "--fdpass", strategy, clam.Path); err != nil {
|
||||
return fmt.Errorf("clamdscan failed, %v", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
+41
-19
@@ -1,8 +1,17 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
sudoHandleCmd string
|
||||
sudoCheckOnce sync.Once
|
||||
)
|
||||
|
||||
func CheckIllegal(args ...string) bool {
|
||||
@@ -21,27 +30,40 @@ func CheckIllegal(args ...string) bool {
|
||||
}
|
||||
|
||||
func SudoHandleCmd() string {
|
||||
cmd := exec.Command("sudo", "-n", "ls")
|
||||
if err := cmd.Run(); err == nil {
|
||||
return "sudo "
|
||||
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 ""
|
||||
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 {
|
||||
// Prefer Go's built-in PATH lookup so we don't depend on an external
|
||||
// `which` binary, which is not installed by default on minimal
|
||||
// distributions (e.g. Arch Linux, some Alpine images, slim containers).
|
||||
// See 1Panel-dev/1Panel#12605.
|
||||
if _, err := exec.LookPath(name); err == nil {
|
||||
return true
|
||||
}
|
||||
// Fall back to shelling out for environments where PATH inside the
|
||||
// agent process differs from the user's interactive shell PATH (the
|
||||
// previous behaviour, preserved for compatibility).
|
||||
stdout, err := RunDefaultWithStdoutBashCf("which %s", name)
|
||||
if err != nil || (len(strings.ReplaceAll(stdout, "\n", "")) == 0) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
_, err := exec.LookPath(name)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
+286
-61
@@ -5,10 +5,12 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -17,11 +19,14 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
)
|
||||
|
||||
const maxStreamOutputCapture = 64 * 1024
|
||||
|
||||
type CommandHelper struct {
|
||||
context context.Context
|
||||
workDir string
|
||||
outputFile string
|
||||
scriptPath string
|
||||
env []string
|
||||
timeout time.Duration
|
||||
taskItem *task.Task
|
||||
logger *log.Logger
|
||||
@@ -30,6 +35,46 @@ type CommandHelper struct {
|
||||
|
||||
type Option func(*CommandHelper)
|
||||
|
||||
type PipeCommand struct {
|
||||
Name string
|
||||
Args []string
|
||||
Env []string
|
||||
Dir string
|
||||
Stdin io.Reader
|
||||
}
|
||||
|
||||
type lockedBuffer struct {
|
||||
mu sync.Mutex
|
||||
buf bytes.Buffer
|
||||
limit int
|
||||
truncated int
|
||||
}
|
||||
|
||||
func (b *lockedBuffer) Write(p []byte) (int, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.limit > 0 && b.buf.Len() >= b.limit {
|
||||
b.truncated += len(p)
|
||||
return len(p), nil
|
||||
}
|
||||
if b.limit > 0 && b.buf.Len()+len(p) > b.limit {
|
||||
keep := b.limit - b.buf.Len()
|
||||
_, _ = b.buf.Write(p[:keep])
|
||||
b.truncated += len(p) - keep
|
||||
return len(p), nil
|
||||
}
|
||||
return b.buf.Write(p)
|
||||
}
|
||||
|
||||
func (b *lockedBuffer) String() string {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.truncated == 0 {
|
||||
return b.buf.String()
|
||||
}
|
||||
return fmt.Sprintf("%s\n... truncated %d bytes ...", b.buf.String(), b.truncated)
|
||||
}
|
||||
|
||||
func NewCommandMgr(opts ...Option) *CommandHelper {
|
||||
s := &CommandHelper{}
|
||||
for _, opt := range opts {
|
||||
@@ -38,82 +83,214 @@ func NewCommandMgr(opts ...Option) *CommandHelper {
|
||||
return s
|
||||
}
|
||||
|
||||
func RunDefaultBashC(command string) error {
|
||||
mgr := NewCommandMgr()
|
||||
return mgr.RunBashC(command)
|
||||
func RunDockerExecWithStdout(timeout time.Duration, containerName string, args ...string) (string, error) {
|
||||
commandArgs := append([]string{"exec", containerName}, args...)
|
||||
return NewCommandMgr(WithTimeout(timeout)).RunWithStdout("docker", commandArgs...)
|
||||
}
|
||||
func RunDefaultBashCf(command string, arg ...interface{}) error {
|
||||
mgr := NewCommandMgr()
|
||||
return mgr.RunBashCf(command, arg...)
|
||||
}
|
||||
func RunDefaultWithStdoutBashC(command string) (string, error) {
|
||||
mgr := NewCommandMgr(WithTimeout(20 * time.Second))
|
||||
return mgr.RunWithStdoutBashC(command)
|
||||
}
|
||||
func RunDefaultWithStdoutBashCf(command string, arg ...interface{}) (string, error) {
|
||||
mgr := NewCommandMgr(WithTimeout(20 * time.Second))
|
||||
return mgr.RunWithStdoutBashCf(command, arg...)
|
||||
}
|
||||
func RunDefaultWithStdoutBashCfAndTimeOut(command string, timeout time.Duration, arg ...interface{}) (string, error) {
|
||||
mgr := NewCommandMgr(WithTimeout(timeout))
|
||||
return mgr.RunWithStdoutBashCf(command, arg...)
|
||||
func RunDockerExec(timeout time.Duration, containerName string, args ...string) error {
|
||||
commandArgs := append([]string{"exec", containerName}, args...)
|
||||
return NewCommandMgr(WithTimeout(timeout)).Run("docker", commandArgs...)
|
||||
}
|
||||
|
||||
func (c *CommandHelper) Run(name string, arg ...string) error {
|
||||
_, err := c.run(name, arg...)
|
||||
return err
|
||||
}
|
||||
func (c *CommandHelper) RunBashCWithArgs(arg ...string) error {
|
||||
arg = append([]string{"-c"}, arg...)
|
||||
_, err := c.run("bash", arg...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *CommandHelper) RunBashC(command string) error {
|
||||
if _, err := c.run("bash", "-c", command); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c *CommandHelper) RunBashCf(command string, arg ...interface{}) error {
|
||||
if _, err := c.run("bash", "-c", fmt.Sprintf(command, arg...)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
func (c *CommandHelper) RunWithOptionalSudo(name string, arg ...string) error {
|
||||
commandName, commandArgs := WrapWithOptionalSudo(name, arg...)
|
||||
return c.Run(commandName, commandArgs...)
|
||||
}
|
||||
|
||||
func (c *CommandHelper) RunWithStdout(name string, arg ...string) (string, error) {
|
||||
return c.run(name, arg...)
|
||||
}
|
||||
func (c *CommandHelper) RunWithStdoutBashC(command string) (string, error) {
|
||||
return c.run("bash", "-c", command)
|
||||
|
||||
func (c *CommandHelper) RunWithOptionalSudoAndStdout(name string, arg ...string) (string, error) {
|
||||
commandName, commandArgs := WrapWithOptionalSudo(name, arg...)
|
||||
return c.RunWithStdout(commandName, commandArgs...)
|
||||
}
|
||||
func (c *CommandHelper) RunWithStdoutBashCf(command string, arg ...interface{}) (string, error) {
|
||||
return c.run("bash", "-c", fmt.Sprintf(command, arg...))
|
||||
|
||||
func (c *CommandHelper) RunPipe(commands ...PipeCommand) (string, error) {
|
||||
if len(commands) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ctx, cancel := c.pipeContext()
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
cmds := c.buildPipeCommands(ctx, commands)
|
||||
customWriter := &CustomWriter{taskItem: c.taskItem}
|
||||
var outputFile *os.File
|
||||
limitOutputCapture := c.taskItem != nil || c.logger != nil || len(c.outputFile) != 0
|
||||
stdout, stderr := &lockedBuffer{}, &lockedBuffer{}
|
||||
if limitOutputCapture {
|
||||
stdout.limit = maxStreamOutputCapture
|
||||
stderr.limit = maxStreamOutputCapture
|
||||
}
|
||||
if commands[0].Stdin != nil {
|
||||
cmds[0].Stdin = commands[0].Stdin
|
||||
}
|
||||
var pipeStderr io.Writer = stderr
|
||||
var lastStdout io.Writer = stdout
|
||||
var lastStderr io.Writer = stderr
|
||||
var streamWriter io.Writer
|
||||
var streamClosers []io.Closer
|
||||
if c.taskItem != nil {
|
||||
streamWriter = customWriter
|
||||
} else if c.logger != nil {
|
||||
streamWriter = c.logger.Writer()
|
||||
if closer, ok := streamWriter.(io.Closer); ok {
|
||||
streamClosers = append(streamClosers, closer)
|
||||
}
|
||||
} else if len(c.outputFile) != 0 {
|
||||
file, err := os.OpenFile(c.outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, constant.FilePerm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
outputFile = file
|
||||
lastStdout = outputFile
|
||||
}
|
||||
if streamWriter != nil {
|
||||
pipeStderr = io.MultiWriter(stderr, streamWriter)
|
||||
lastStdout = io.MultiWriter(stdout, streamWriter)
|
||||
lastStderr = io.MultiWriter(stderr, streamWriter)
|
||||
}
|
||||
defer func() {
|
||||
if c.taskItem != nil {
|
||||
customWriter.Flush()
|
||||
}
|
||||
for _, closer := range streamClosers {
|
||||
_ = closer.Close()
|
||||
}
|
||||
if outputFile != nil {
|
||||
_ = outputFile.Close()
|
||||
}
|
||||
}()
|
||||
if err := connectPipeCommands(cmds, lastStdout, lastStderr, pipeStderr); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := startPipeCommands(cmds); err != nil {
|
||||
return handleErrString(stdout.String(), stderr.String(), c.IgnoreExist1, err)
|
||||
}
|
||||
|
||||
runErr := waitPipeCommands(ctx, cmds)
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return "", buserr.New("ErrCmdTimeout")
|
||||
}
|
||||
if errors.Is(ctx.Err(), context.Canceled) {
|
||||
return "", buserr.New("ErrShutDown")
|
||||
}
|
||||
if runErr != nil {
|
||||
return handleErrString(stdout.String(), stderr.String(), c.IgnoreExist1, runErr)
|
||||
}
|
||||
return stdout.String(), nil
|
||||
}
|
||||
|
||||
func (c *CommandHelper) pipeContext() (context.Context, context.CancelFunc) {
|
||||
ctx := c.context
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
if c.timeout == 0 {
|
||||
return ctx, nil
|
||||
}
|
||||
return context.WithTimeout(ctx, c.timeout)
|
||||
}
|
||||
|
||||
func (c *CommandHelper) buildPipeCommands(ctx context.Context, commands []PipeCommand) []*exec.Cmd {
|
||||
cmds := make([]*exec.Cmd, 0, len(commands))
|
||||
for _, item := range commands {
|
||||
cmdItem := exec.CommandContext(ctx, item.Name, item.Args...)
|
||||
cmdItem.Env = append(os.Environ(), c.env...)
|
||||
cmdItem.Env = append(cmdItem.Env, item.Env...)
|
||||
cmdItem.Dir = c.workDir
|
||||
if item.Dir != "" {
|
||||
cmdItem.Dir = item.Dir
|
||||
}
|
||||
cmdItem.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
cmds = append(cmds, cmdItem)
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
||||
func connectPipeCommands(cmds []*exec.Cmd, stdout, stderr, pipeStderr io.Writer) error {
|
||||
for i := 0; i < len(cmds)-1; i++ {
|
||||
pipe, err := cmds[i].StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmds[i+1].Stdin = pipe
|
||||
cmds[i].Stderr = pipeStderr
|
||||
}
|
||||
last := cmds[len(cmds)-1]
|
||||
last.Stdout = stdout
|
||||
last.Stderr = stderr
|
||||
return nil
|
||||
}
|
||||
|
||||
func startPipeCommands(cmds []*exec.Cmd) error {
|
||||
for i := len(cmds) - 1; i >= 0; i-- {
|
||||
if err := cmds[i].Start(); err != nil {
|
||||
killStarted(cmds[i+1:])
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitPipeCommands(ctx context.Context, cmds []*exec.Cmd) error {
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
var runErr error
|
||||
for _, item := range cmds {
|
||||
if err := item.Wait(); err != nil && runErr == nil {
|
||||
runErr = err
|
||||
}
|
||||
}
|
||||
done <- runErr
|
||||
}()
|
||||
select {
|
||||
case runErr := <-done:
|
||||
return runErr
|
||||
case <-ctx.Done():
|
||||
killProcessGroups(cmds)
|
||||
return <-done
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
var cmd *exec.Cmd
|
||||
var newContext context.Context
|
||||
var cancel context.CancelFunc
|
||||
var outputFile *os.File
|
||||
|
||||
if c.timeout != 0 {
|
||||
if c.context == nil {
|
||||
newContext, cancel = context.WithTimeout(context.Background(), c.timeout)
|
||||
defer cancel()
|
||||
} else {
|
||||
newContext, cancel = context.WithTimeout(c.context, c.timeout)
|
||||
defer cancel()
|
||||
}
|
||||
defer cancel()
|
||||
} else if c.context != nil {
|
||||
newContext = c.context
|
||||
}
|
||||
|
||||
if len(c.scriptPath) != 0 {
|
||||
if newContext != nil {
|
||||
cmd = exec.CommandContext(newContext, "bash", c.scriptPath)
|
||||
} else {
|
||||
cmd = exec.Command("bash", c.scriptPath)
|
||||
}
|
||||
} else if newContext != nil {
|
||||
cmd = exec.CommandContext(newContext, name, arg...)
|
||||
} else {
|
||||
if c.context == nil {
|
||||
newContext = context.Background()
|
||||
cmd = exec.Command(name, arg...)
|
||||
} else {
|
||||
newContext = c.context
|
||||
cmd = exec.CommandContext(c.context, name, arg...)
|
||||
}
|
||||
cmd = exec.Command(name, arg...)
|
||||
}
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
@@ -121,36 +298,50 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
|
||||
customWriter := &CustomWriter{taskItem: c.taskItem}
|
||||
var stdout, stderr bytes.Buffer
|
||||
var loggerClosers []io.Closer
|
||||
if c.taskItem != nil {
|
||||
cmd.Stdout = customWriter
|
||||
cmd.Stderr = customWriter
|
||||
} else if c.logger != nil {
|
||||
cmd.Stdout = c.logger.Writer()
|
||||
cmd.Stderr = c.logger.Writer()
|
||||
stdoutWriter := c.logger.Writer()
|
||||
stderrWriter := c.logger.Writer()
|
||||
if closer, ok := stdoutWriter.(io.Closer); ok {
|
||||
loggerClosers = append(loggerClosers, closer)
|
||||
}
|
||||
if closer, ok := stderrWriter.(io.Closer); ok {
|
||||
loggerClosers = append(loggerClosers, closer)
|
||||
}
|
||||
cmd.Stdout = stdoutWriter
|
||||
cmd.Stderr = stderrWriter
|
||||
} else if len(c.outputFile) != 0 {
|
||||
file, err := os.OpenFile(c.outputFile, os.O_WRONLY|os.O_CREATE, constant.FilePerm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
cmd.Stdout = file
|
||||
cmd.Stderr = file
|
||||
} else if len(c.scriptPath) != 0 {
|
||||
cmd = exec.Command("bash", c.scriptPath)
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
outputFile = file
|
||||
cmd.Stdout = outputFile
|
||||
cmd.Stderr = outputFile
|
||||
} else {
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
}
|
||||
env := os.Environ()
|
||||
env = append(env, c.env...)
|
||||
cmd.Env = env
|
||||
if len(c.workDir) != 0 {
|
||||
cmd.Dir = c.workDir
|
||||
}
|
||||
defer func() {
|
||||
for _, closer := range loggerClosers {
|
||||
_ = closer.Close()
|
||||
}
|
||||
if outputFile != nil {
|
||||
_ = outputFile.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return "", fmt.Errorf("cmd.Start() failed with '%s'\n", err)
|
||||
return "", fmt.Errorf("cmd start failed: %w", err)
|
||||
}
|
||||
if c.taskItem != nil {
|
||||
defer customWriter.Flush()
|
||||
@@ -166,9 +357,10 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
return handleErr(stdout, stderr, c.IgnoreExist1, err)
|
||||
}
|
||||
return stdout.String(), nil
|
||||
case <-newContext.Done():
|
||||
case <-contextDone(newContext):
|
||||
if cmd.Process != nil && cmd.Process.Pid > 0 {
|
||||
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
killErr := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
_ = killErr
|
||||
}
|
||||
var err error
|
||||
switch newContext.Err() {
|
||||
@@ -184,6 +376,30 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func contextDone(ctx context.Context) <-chan struct{} {
|
||||
if ctx == nil {
|
||||
return nil
|
||||
}
|
||||
return ctx.Done()
|
||||
}
|
||||
|
||||
func killStarted(cmds []*exec.Cmd) {
|
||||
killProcessGroups(cmds)
|
||||
for _, item := range cmds {
|
||||
if item.Process != nil {
|
||||
_ = item.Wait()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func killProcessGroups(cmds []*exec.Cmd) {
|
||||
for _, item := range cmds {
|
||||
if item.Process != nil {
|
||||
_ = syscall.Kill(-item.Process.Pid, syscall.SIGKILL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithContext(ctx context.Context) Option {
|
||||
return func(s *CommandHelper) {
|
||||
s.context = ctx
|
||||
@@ -219,6 +435,11 @@ func WithScriptPath(scriptPath string) Option {
|
||||
s.scriptPath = scriptPath
|
||||
}
|
||||
}
|
||||
func WithEnv(env ...string) Option {
|
||||
return func(s *CommandHelper) {
|
||||
s.env = append(s.env, env...)
|
||||
}
|
||||
}
|
||||
func WithIgnoreExist1() Option {
|
||||
return func(s *CommandHelper) {
|
||||
s.IgnoreExist1 = true
|
||||
@@ -250,6 +471,10 @@ func (cw *CustomWriter) Flush() {
|
||||
}
|
||||
|
||||
func handleErr(stdout, stderr bytes.Buffer, ignoreExist1 bool, err error) (string, error) {
|
||||
return handleErrString(stdout.String(), stderr.String(), ignoreExist1, err)
|
||||
}
|
||||
|
||||
func handleErrString(stdout, stderr string, ignoreExist1 bool, err error) (string, error) {
|
||||
var exitError *exec.ExitError
|
||||
if ignoreExist1 && errors.As(err, &exitError) {
|
||||
if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
|
||||
@@ -258,8 +483,8 @@ func handleErr(stdout, stderr bytes.Buffer, ignoreExist1 bool, err error) (strin
|
||||
}
|
||||
}
|
||||
}
|
||||
outItem := stdout.String()
|
||||
errItem := stderr.String()
|
||||
outItem := stdout
|
||||
errItem := stderr
|
||||
if len(errItem) != 0 && len(outItem) != 0 {
|
||||
return outItem, fmt.Errorf("stdout: %s; stderr: %s, err: %v", outItem, errItem, err)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ctl_conf"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
@@ -289,18 +290,21 @@ func LoadTimeZoneByCmd() string {
|
||||
if _, err := time.LoadLocation(loc); err != nil {
|
||||
loc = "Asia/Shanghai"
|
||||
}
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("timedatectl | grep 'Time zone'")
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)).RunWithStdout("timedatectl")
|
||||
if err != nil {
|
||||
return loc
|
||||
}
|
||||
fields := strings.Fields(string(std))
|
||||
if len(fields) != 5 {
|
||||
return loc
|
||||
for _, line := range strings.Split(std, "\n") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) != 5 || fields[0] != "Time" || fields[1] != "zone:" {
|
||||
continue
|
||||
}
|
||||
if _, err := time.LoadLocation(fields[2]); err != nil {
|
||||
return loc
|
||||
}
|
||||
return fields[2]
|
||||
}
|
||||
if _, err := time.LoadLocation(fields[2]); err != nil {
|
||||
return loc
|
||||
}
|
||||
return fields[2]
|
||||
return loc
|
||||
}
|
||||
|
||||
func IsValidDomain(domain string) bool {
|
||||
@@ -442,20 +446,8 @@ func GetDockerComposeCommand() string {
|
||||
}
|
||||
|
||||
func LoadParams(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
info := strings.ReplaceAll(stdout, "\n", "")
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param))
|
||||
}
|
||||
return info
|
||||
return ctl_conf.Load(param)
|
||||
}
|
||||
func LoadParamsWithoutPanic(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.ReplaceAll(stdout, "\n", "")
|
||||
return ctl_conf.LoadWithoutPanic(param)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package manager
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
@@ -19,5 +18,5 @@ func handlerErr(out string, err error) error {
|
||||
}
|
||||
|
||||
func run(name string, args ...string) (string, error) {
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(10*time.Second)).RunWithStdoutBashCf("LANGUAGE=en_US:en %s %s", name, strings.Join(args, " "))
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(10*time.Second), cmd.WithEnv("LANGUAGE=en_US:en")).RunWithStdout(name, args...)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
)
|
||||
@@ -18,18 +19,11 @@ func (s *Openrc) Name() string {
|
||||
return "openrc"
|
||||
}
|
||||
func (s *Openrc) IsActive(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if service %s status >/dev/null 2>&1; then echo 'active'; else echo 'inactive'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "active\n", nil
|
||||
_, err := cmd.NewCommandMgr().RunWithStdout("service", serviceName, "status")
|
||||
return err == nil, nil
|
||||
}
|
||||
func (s *Openrc) IsEnable(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if ls /etc/rc*.d/S*%s >/dev/null 2>&1; then echo 'enabled'; else echo 'disabled'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "enabled\n", nil
|
||||
return isSysvServiceEnabled(serviceName)
|
||||
}
|
||||
func (s *Openrc) IsExist(serviceName string) (bool, error) {
|
||||
_, err := os.Stat(filepath.Join("/etc/init.d", serviceName))
|
||||
@@ -59,3 +53,27 @@ func (s *Openrc) Operate(operate, serviceName string) error {
|
||||
func (s *Openrc) Reload() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isSysvServiceEnabled(serviceName string) (bool, error) {
|
||||
entries, err := os.ReadDir("/etc")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
name := entry.Name()
|
||||
if !entry.IsDir() || !strings.HasPrefix(name, "rc") || !strings.HasSuffix(name, ".d") {
|
||||
continue
|
||||
}
|
||||
items, err := os.ReadDir(filepath.Join("/etc", name))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, item := range items {
|
||||
itemName := item.Name()
|
||||
if strings.HasPrefix(itemName, "S") && strings.HasSuffix(itemName, serviceName) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -18,18 +18,11 @@ func (s *Sysvinit) Name() string {
|
||||
return "sysvinit"
|
||||
}
|
||||
func (s *Sysvinit) IsActive(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if service %s status >/dev/null 2>&1; then echo 'active'; else echo 'inactive'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "active\n", nil
|
||||
_, err := cmd.NewCommandMgr().RunWithStdout("service", serviceName, "status")
|
||||
return err == nil, nil
|
||||
}
|
||||
func (s *Sysvinit) IsEnable(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if ls /etc/rc*.d/S*%s >/dev/null 2>&1; then echo 'enabled'; else echo 'disabled'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "enabled\n", nil
|
||||
return isSysvServiceEnabled(serviceName)
|
||||
}
|
||||
func (s *Sysvinit) IsExist(serviceName string) (bool, error) {
|
||||
_, err := os.Stat(filepath.Join("/etc/init.d", serviceName))
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package ctl_conf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const defaultFile = "/usr/local/bin/1pctl"
|
||||
|
||||
func Load(key string) string {
|
||||
info, err := LoadFromFile(defaultFile, key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic(fmt.Sprintf("error `%s` find in %s", key, defaultFile))
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func LoadWithoutPanic(key string) string {
|
||||
info, err := LoadFromFile(defaultFile, key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func LoadFromFile(filePath, key string) (string, error) {
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
prefix := key + "="
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.HasPrefix(line, prefix) {
|
||||
return strings.TrimSpace(strings.TrimPrefix(line, prefix)), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("error `%s` find in %s", key, filePath)
|
||||
}
|
||||
|
||||
func UpdateInFile(filePath, key, value string) error {
|
||||
return rewriteFile(filePath, func(line string) (string, bool) {
|
||||
if strings.HasPrefix(line, key+"=") {
|
||||
return key + "=" + value, true
|
||||
}
|
||||
return line, true
|
||||
})
|
||||
}
|
||||
|
||||
func RemoveValueFromFile(filePath, key, value string) error {
|
||||
target := key + "=" + value
|
||||
return rewriteFile(filePath, func(line string) (string, bool) {
|
||||
return line, line != target
|
||||
})
|
||||
}
|
||||
|
||||
func rewriteFile(filePath string, rewrite func(string) (string, bool)) error {
|
||||
info, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content := rewriteLines(string(data), rewrite)
|
||||
return os.WriteFile(filePath, []byte(content), info.Mode().Perm())
|
||||
}
|
||||
|
||||
func rewriteLines(data string, rewrite func(string) (string, bool)) string {
|
||||
hasTrailingNewline := strings.HasSuffix(data, "\n")
|
||||
lines := strings.Split(strings.TrimSuffix(data, "\n"), "\n")
|
||||
rewritten := make([]string, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
newLine, keep := rewrite(line)
|
||||
if keep {
|
||||
rewritten = append(rewritten, newLine)
|
||||
}
|
||||
}
|
||||
content := strings.Join(rewritten, "\n")
|
||||
if hasTrailingNewline {
|
||||
content += "\n"
|
||||
}
|
||||
return content
|
||||
}
|
||||
@@ -173,14 +173,23 @@ func (f FileOp) CleanDir(dst string) error {
|
||||
if IsProtected(dst) {
|
||||
return buserr.New("ErrPathNotDelete")
|
||||
}
|
||||
return cmd.RunDefaultBashCf("rm -rf %s/*", dst)
|
||||
items, err := afero.ReadDir(f.Fs, dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, item := range items {
|
||||
if err := f.Fs.RemoveAll(filepath.Join(dst, item.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) RmRf(dst string) error {
|
||||
if IsProtected(dst) {
|
||||
return buserr.New("ErrPathNotDelete")
|
||||
}
|
||||
return cmd.RunDefaultBashCf("rm -rf %s", dst)
|
||||
return f.Fs.RemoveAll(dst)
|
||||
}
|
||||
|
||||
func (f FileOp) WriteFile(dst string, in io.Reader, mode fs.FileMode) error {
|
||||
@@ -231,48 +240,48 @@ func (f FileOp) SaveFileWithByte(dst string, content []byte, mode fs.FileMode) e
|
||||
}
|
||||
|
||||
func (f FileOp) ChownR(dst string, uid string, gid string, sub bool) error {
|
||||
cmdStr := fmt.Sprintf(`%s chown %s:%s "%s"`, cmd.SudoHandleCmd(), uid, gid, dst)
|
||||
args := []string{uid + ":" + gid, dst}
|
||||
if sub {
|
||||
cmdStr = fmt.Sprintf(`chown -R %s:%s "%s"`, uid, gid, dst)
|
||||
args = append([]string{"-R", uid + ":" + gid}, dst)
|
||||
}
|
||||
timeout := cmdDefaultTimeout
|
||||
if sub {
|
||||
timeout = cmdRecursiveTimeout
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout))
|
||||
if err := cmdMgr.RunBashC(cmdStr); err != nil {
|
||||
if err := cmdMgr.RunWithOptionalSudo("chown", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) ChmodR(dst string, mode int64, sub bool) error {
|
||||
cmdStr := fmt.Sprintf(`%s chmod %v "%s"`, cmd.SudoHandleCmd(), fmt.Sprintf("%04o", mode), dst)
|
||||
args := []string{fmt.Sprintf("%04o", mode), dst}
|
||||
if sub {
|
||||
cmdStr = fmt.Sprintf(`%s chmod -R %v "%s"`, cmd.SudoHandleCmd(), fmt.Sprintf("%04o", mode), dst)
|
||||
args = append([]string{"-R", fmt.Sprintf("%04o", mode)}, dst)
|
||||
}
|
||||
timeout := cmdDefaultTimeout
|
||||
if sub {
|
||||
timeout = cmdRecursiveTimeout
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout))
|
||||
if err := cmdMgr.RunBashC(cmdStr); err != nil {
|
||||
if err := cmdMgr.RunWithOptionalSudo("chmod", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) ChmodRWithMode(dst string, mode fs.FileMode, sub bool) error {
|
||||
cmdStr := fmt.Sprintf(`%s chmod %v "%s"`, cmd.SudoHandleCmd(), fmt.Sprintf("%o", mode.Perm()), dst)
|
||||
args := []string{fmt.Sprintf("%o", mode.Perm()), dst}
|
||||
if sub {
|
||||
cmdStr = fmt.Sprintf(`%s chmod -R %v "%s"`, cmd.SudoHandleCmd(), fmt.Sprintf("%o", mode.Perm()), dst)
|
||||
args = append([]string{"-R", fmt.Sprintf("%o", mode.Perm())}, dst)
|
||||
}
|
||||
timeout := cmdDefaultTimeout
|
||||
if sub {
|
||||
timeout = cmdRecursiveTimeout
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout))
|
||||
if err := cmdMgr.RunBashC(cmdStr); err != nil {
|
||||
if err := cmdMgr.RunWithOptionalSudo("chmod", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -285,23 +294,18 @@ func (f FileOp) ChownRPaths(paths []string, uid string, gid string, sub bool) er
|
||||
if len(paths) == 1 {
|
||||
return f.ChownR(paths[0], uid, gid, sub)
|
||||
}
|
||||
quoted := make([]string, len(paths))
|
||||
for i, p := range paths {
|
||||
quoted[i] = fmt.Sprintf(`"%s"`, p)
|
||||
}
|
||||
args := strings.Join(quoted, " ")
|
||||
var cmdStr string
|
||||
args := []string{uid + ":" + gid}
|
||||
if sub {
|
||||
cmdStr = fmt.Sprintf(`chown -R %s:%s %s`, uid, gid, args)
|
||||
args = append([]string{"-R", uid + ":" + gid}, paths...)
|
||||
} else {
|
||||
cmdStr = fmt.Sprintf(`%s chown %s:%s %s`, cmd.SudoHandleCmd(), uid, gid, args)
|
||||
args = append(args, paths...)
|
||||
}
|
||||
timeout := cmdDefaultTimeout
|
||||
if sub {
|
||||
timeout = cmdRecursiveTimeout
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout))
|
||||
if err := cmdMgr.RunBashC(cmdStr); err != nil {
|
||||
if err := cmdMgr.RunWithOptionalSudo("chown", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -314,24 +318,19 @@ func (f FileOp) ChmodRPaths(paths []string, mode int64, sub bool) error {
|
||||
if len(paths) == 1 {
|
||||
return f.ChmodR(paths[0], mode, sub)
|
||||
}
|
||||
quoted := make([]string, len(paths))
|
||||
for i, p := range paths {
|
||||
quoted[i] = fmt.Sprintf(`"%s"`, p)
|
||||
}
|
||||
args := strings.Join(quoted, " ")
|
||||
modeStr := fmt.Sprintf("%04o", mode)
|
||||
var cmdStr string
|
||||
args := []string{modeStr}
|
||||
if sub {
|
||||
cmdStr = fmt.Sprintf(`%s chmod -R %s %s`, cmd.SudoHandleCmd(), modeStr, args)
|
||||
args = append([]string{"-R", modeStr}, paths...)
|
||||
} else {
|
||||
cmdStr = fmt.Sprintf(`%s chmod %s %s`, cmd.SudoHandleCmd(), modeStr, args)
|
||||
args = append(args, paths...)
|
||||
}
|
||||
timeout := cmdDefaultTimeout
|
||||
if sub {
|
||||
timeout = cmdRecursiveTimeout
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(timeout))
|
||||
if err := cmdMgr.RunBashC(cmdStr); err != nil {
|
||||
if err := cmdMgr.RunWithOptionalSudo("chmod", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -543,19 +542,20 @@ func (f FileOp) Cut(oldPaths []string, dst, name string, cover bool) error {
|
||||
dstPath = dst
|
||||
coverFlag = "-f"
|
||||
}
|
||||
var quotedPaths []string
|
||||
for _, p := range oldPaths {
|
||||
quotedPaths = append(quotedPaths, fmt.Sprintf("'%s'", p))
|
||||
args := []string{}
|
||||
if coverFlag != "" {
|
||||
args = append(args, coverFlag)
|
||||
}
|
||||
mvCommand := fmt.Sprintf("mv %s %s '%s'", coverFlag, strings.Join(quotedPaths, " "), dstPath)
|
||||
if err := cmd.RunDefaultBashC(mvCommand); err != nil {
|
||||
args = append(args, oldPaths...)
|
||||
args = append(args, dstPath)
|
||||
if err := cmd.NewCommandMgr().Run("mv", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) Mv(oldPath, dstPath string) error {
|
||||
if err := cmd.RunDefaultBashCf(`mv '%s' '%s'`, oldPath, dstPath); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("mv", oldPath, dstPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -611,22 +611,22 @@ func (f FileOp) CopyAndReName(src, dst, name string, cover bool) error {
|
||||
if name != "" && !cover {
|
||||
dstPath = filepath.Join(dst, name)
|
||||
}
|
||||
return cmd.RunDefaultBashCf(`cp -rfp '%s' '%s'`, src, dstPath)
|
||||
return cmd.NewCommandMgr().Run("cp", "-rfp", src, dstPath)
|
||||
} else {
|
||||
dstPath := filepath.Join(dst, name)
|
||||
if cover {
|
||||
dstPath = dst
|
||||
}
|
||||
return cmd.RunDefaultBashCf(`cp -fp '%s' '%s'`, src, dstPath)
|
||||
return cmd.NewCommandMgr().Run("cp", "-fp", src, dstPath)
|
||||
}
|
||||
}
|
||||
|
||||
func (f FileOp) CopyDirWithNewName(src, dst, newName string) error {
|
||||
if newName == "." || newName == "" {
|
||||
return cmd.RunDefaultBashCf(`cp -rfp '%s'/. '%s'`, src, dst)
|
||||
return cmd.NewCommandMgr().Run("cp", "-rfp", filepath.Clean(src)+"/.", dst)
|
||||
}
|
||||
dstDir := filepath.Join(dst, newName)
|
||||
return cmd.RunDefaultBashCf(`cp -rfp '%s' '%s'`, src, dstDir)
|
||||
return cmd.NewCommandMgr().Run("cp", "-rfp", src, dstDir)
|
||||
}
|
||||
|
||||
func (f FileOp) CopyDir(src, dst string) error {
|
||||
@@ -638,7 +638,7 @@ func (f FileOp) CopyDir(src, dst string) error {
|
||||
if err = f.Fs.MkdirAll(dstDir, srcInfo.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithIgnoreExist1()).RunBashCf(`cp -rfp '%s' '%s'`, src, dst+"/")
|
||||
return cmd.NewCommandMgr(cmd.WithIgnoreExist1()).Run("cp", "-rfp", src, dst+"/")
|
||||
}
|
||||
|
||||
func (f FileOp) CopyDirWithExclude(src, dst string, excludeNames []string) error {
|
||||
@@ -651,7 +651,7 @@ func (f FileOp) CopyDirWithExclude(src, dst string, excludeNames []string) error
|
||||
return err
|
||||
}
|
||||
if len(excludeNames) == 0 {
|
||||
return cmd.NewCommandMgr(cmd.WithIgnoreExist1()).RunBashCf(`cp -rfp '%s' '%s'`, src, dst+"/")
|
||||
return cmd.NewCommandMgr(cmd.WithIgnoreExist1()).Run("cp", "-rfp", src, dst+"/")
|
||||
}
|
||||
tmpFiles, err := os.ReadDir(src)
|
||||
if err != nil {
|
||||
@@ -684,7 +684,7 @@ func (f FileOp) CopyDirWithExclude(src, dst string, excludeNames []string) error
|
||||
|
||||
func (f FileOp) CopyFile(src, dst string) error {
|
||||
dst = filepath.Clean(dst) + string(filepath.Separator)
|
||||
return cmd.NewCommandMgr(cmd.WithIgnoreExist1()).RunBashCf(`cp -fp '%s' '%s'`, src, dst+"/")
|
||||
return cmd.NewCommandMgr(cmd.WithIgnoreExist1()).Run("cp", "-fp", src, dst+"/")
|
||||
}
|
||||
|
||||
func (f FileOp) GetDirSize(path string) (int64, error) {
|
||||
@@ -1263,10 +1263,8 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
|
||||
workdir = path.Dir(src)
|
||||
srcItem = path.Base(src)
|
||||
}
|
||||
commands := ""
|
||||
|
||||
exMap := make(map[string]struct{})
|
||||
exStr := ""
|
||||
excludeArgs := []string{}
|
||||
excludes := strings.Split(exclusionRules, ",")
|
||||
for _, exclude := range excludes {
|
||||
if len(exclude) == 0 {
|
||||
@@ -1278,19 +1276,18 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
|
||||
if _, ok := exMap[exclude]; ok {
|
||||
continue
|
||||
}
|
||||
exStr += fmt.Sprintf(" --exclude '%s'", exclude)
|
||||
excludeArgs = append(excludeArgs, "--exclude", exclude)
|
||||
exMap[exclude] = struct{}{}
|
||||
}
|
||||
|
||||
tarArgs := append([]string{}, excludeArgs...)
|
||||
if len(secret) != 0 {
|
||||
commands = fmt.Sprintf("tar %s -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", exStr, srcItem, secret, dst)
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir), cmd.WithIgnoreExist1())
|
||||
return runTarGzEncryptToFile(cmdMgr, dst, secret, append(tarArgs, srcItem)...)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zcf %s %s %s", dst, exStr, srcItem)
|
||||
global.LOG.Debug(commands)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir), cmd.WithIgnoreExist1())
|
||||
return runTarGzToFile(cmdMgr, dst, append(tarArgs, srcItem)...)
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir), cmd.WithIgnoreExist1())
|
||||
return cmdMgr.RunBashC(commands)
|
||||
}
|
||||
|
||||
func (f FileOp) TarGzFilesWithCompressPro(list []string, dst, secret string) error {
|
||||
@@ -1300,20 +1297,17 @@ func (f FileOp) TarGzFilesWithCompressPro(list []string, dst, secret string) err
|
||||
}
|
||||
}
|
||||
|
||||
var filelist []string
|
||||
var tarArgs []string
|
||||
for _, item := range list {
|
||||
filelist = append(filelist, "-C '"+path.Dir(item)+"' '"+path.Base(item)+"' ")
|
||||
tarArgs = append(tarArgs, "-C", path.Dir(item), path.Base(item))
|
||||
}
|
||||
commands := ""
|
||||
if len(secret) != 0 {
|
||||
commands = fmt.Sprintf("tar -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", strings.Join(filelist, " "), secret, dst)
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1())
|
||||
return runTarGzEncryptToFile(cmdMgr, dst, secret, tarArgs...)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zcf %s %s", dst, strings.Join(filelist, " "))
|
||||
global.LOG.Debug(commands)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1())
|
||||
return runTarGzToFile(cmdMgr, dst, tarArgs...)
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1())
|
||||
return cmdMgr.RunBashC(commands)
|
||||
}
|
||||
|
||||
func (f FileOp) TarGzExtractPro(src, dst string, secret string) error {
|
||||
@@ -1323,19 +1317,13 @@ func (f FileOp) TarGzExtractPro(src, dst string, secret string) error {
|
||||
}
|
||||
}
|
||||
|
||||
commands := ""
|
||||
if len(secret) != 0 {
|
||||
commands = fmt.Sprintf("openssl enc -d -aes-256-cbc -salt -k '%s' -in %s | tar -zxf - > /root/log", secret, src)
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst), cmd.WithIgnoreExist1())
|
||||
return runTarGzDecryptToDir(cmdMgr, src, dst, secret, true)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar zxvf %s", src)
|
||||
global.LOG.Debug(commands)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst), cmd.WithIgnoreExist1())
|
||||
return runTarGzExtractToDir(cmdMgr, src, dst)
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst), cmd.WithIgnoreExist1())
|
||||
if len(secret) == 0 {
|
||||
return cmdMgr.Run("tar", "zxvf", src)
|
||||
}
|
||||
return cmdMgr.RunBashC(commands)
|
||||
}
|
||||
func CopyCustomAppFile(srcPath, dstPath string) error {
|
||||
if _, err := os.Stat(srcPath); os.IsNotExist(err) {
|
||||
@@ -1375,7 +1363,7 @@ func CopyCustomAppFile(srcPath, dstPath string) error {
|
||||
|
||||
func OpensslEncrypt(filePath, secret string) error {
|
||||
tmpName := path.Join(path.Dir(filePath), "tmp_"+path.Base(filePath))
|
||||
if err := cmd.RunDefaultBashCf("MY_PASS='%s' openssl enc -aes-256-cbc -salt -pass env:MY_PASS -in %s -out %s", secret, filePath, tmpName); err != nil {
|
||||
if err := cmd.NewCommandMgr(cmd.WithEnv("MY_PASS="+secret)).Run("openssl", "enc", "-aes-256-cbc", "-salt", "-pass", "env:MY_PASS", "-in", filePath, "-out", tmpName); err != nil {
|
||||
_ = os.Remove(tmpName)
|
||||
return err
|
||||
}
|
||||
@@ -1384,7 +1372,7 @@ func OpensslEncrypt(filePath, secret string) error {
|
||||
|
||||
func OpensslDecrypt(filePath, secret string) error {
|
||||
tmpName := path.Join(path.Dir(filePath), "tmp_"+path.Base(filePath))
|
||||
if err := cmd.RunDefaultBashCf("MY_PASS='%s' openssl enc -aes-256-cbc -d -salt -pass env:MY_PASS -in %s -out %s", secret, filePath, tmpName); err != nil {
|
||||
if err := cmd.NewCommandMgr(cmd.WithEnv("MY_PASS="+secret)).Run("openssl", "enc", "-aes-256-cbc", "-d", "-salt", "-pass", "env:MY_PASS", "-in", filePath, "-out", tmpName); err != nil {
|
||||
if strings.Contains(err.Error(), "bad decrypt") || strings.Contains(err.Error(), "bad magic number") {
|
||||
return buserr.New("ErrBadDecrypt")
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (z RarArchiver) Extract(ctx context.Context, filePath, dstDir string, _ str
|
||||
if err := checkCmdAvailability("unrar"); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).RunBashCf("unrar x -y -o+ %q %q", filePath, dstDir)
|
||||
return cmd.NewCommandMgr().Run("unrar", "x", "-y", "-o+", filePath, dstDir)
|
||||
}
|
||||
|
||||
func (z RarArchiver) Compress(ctx context.Context, sourcePaths []string, dstFile string, _ string) (err error) {
|
||||
|
||||
@@ -19,7 +19,7 @@ func NewTarArchiver(compressType CompressType) ShellArchiver {
|
||||
}
|
||||
|
||||
func (t TarArchiver) Extract(ctx context.Context, FilePath string, dstDir string, secret string) error {
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).RunBashCf("%s %s \"%s\" -C \"%s\"", t.Cmd, t.getOptionStr("extract"), FilePath, dstDir)
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).Run(t.Cmd, t.getOptionStr("extract"), FilePath, "-C", dstDir)
|
||||
}
|
||||
|
||||
func (t TarArchiver) Compress(ctx context.Context, sourcePaths []string, dstFile string, secret string) error {
|
||||
|
||||
+36
-21
@@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -25,20 +24,11 @@ func (t TarGzArchiver) Extract(ctx context.Context, filePath, dstDir string, sec
|
||||
if err := os.MkdirAll(dstDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create destination dir: %w", err)
|
||||
}
|
||||
var err error
|
||||
commands := ""
|
||||
if len(secret) != 0 {
|
||||
extraCmd := fmt.Sprintf("openssl enc -d -aes-256-cbc -k '%s' -in '%s' | ", secret, filePath)
|
||||
commands = fmt.Sprintf("%s tar -zxvf - -C '%s' > /dev/null 2>&1", extraCmd, dstDir)
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******"))
|
||||
return runTarGzDecryptToDir(cmd.NewCommandMgr(cmd.WithIgnoreExist1()), filePath, dstDir, secret, false)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zxvf '%s' -C '%s' > /dev/null 2>&1", filePath, dstDir)
|
||||
global.LOG.Debug(commands)
|
||||
return runTarGzExtractToDir(cmd.NewCommandMgr(cmd.WithIgnoreExist1()), filePath, dstDir)
|
||||
}
|
||||
if err = cmd.NewCommandMgr(cmd.WithContext(ctx)).RunBashC(commands); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t TarGzArchiver) Compress(ctx context.Context, sourcePaths []string, dstFile string, secret string) error {
|
||||
@@ -54,23 +44,17 @@ func (t TarGzArchiver) Compress(ctx context.Context, sourcePaths []string, dstFi
|
||||
|
||||
var itemDirs []string
|
||||
for _, item := range sourcePaths {
|
||||
itemDirs = append(itemDirs, fmt.Sprintf("\"%s\"", filepath.Base(item)))
|
||||
itemDirs = append(itemDirs, filepath.Base(item))
|
||||
}
|
||||
itemDir := strings.Join(itemDirs, " ")
|
||||
aheadDir := filepath.Dir(sourcePaths[0])
|
||||
if len(aheadDir) == 0 {
|
||||
aheadDir = "/"
|
||||
}
|
||||
commands := ""
|
||||
if len(secret) != 0 {
|
||||
extraCmd := fmt.Sprintf("| openssl enc -aes-256-cbc -salt -k '%s' -out '%s'", secret, tmpFile)
|
||||
commands = fmt.Sprintf("tar -zcf - -C \"%s\" %s %s", aheadDir, itemDir, extraCmd)
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
err = runTarGzEncryptToFile(cmd.NewCommandMgr(cmd.WithContext(ctx)), tmpFile, secret, append([]string{"-C", aheadDir}, itemDirs...)...)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zcf \"%s\" -C \"%s\" %s", tmpFile, aheadDir, itemDir)
|
||||
global.LOG.Debug(commands)
|
||||
err = runTarGzToFile(cmd.NewCommandMgr(cmd.WithContext(ctx)), tmpFile, append([]string{"-C", aheadDir}, itemDirs...)...)
|
||||
}
|
||||
err = cmd.NewCommandMgr(cmd.WithContext(ctx)).RunBashC(commands)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -79,3 +63,34 @@ func (t TarGzArchiver) Compress(ctx context.Context, sourcePaths []string, dstFi
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runTarGzToFile(cmdMgr *cmd.CommandHelper, dst string, tarArgs ...string) error {
|
||||
args := append([]string{"-zcf", dst}, tarArgs...)
|
||||
return cmdMgr.Run("tar", args...)
|
||||
}
|
||||
|
||||
func runTarGzEncryptToFile(cmdMgr *cmd.CommandHelper, dst, secret string, tarArgs ...string) error {
|
||||
args := append([]string{"-zcf", "-"}, tarArgs...)
|
||||
_, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "tar", Args: args},
|
||||
cmd.PipeCommand{Name: "openssl", Args: []string{"enc", "-aes-256-cbc", "-salt", "-pass", "env:BACKUP_SECRET", "-out", dst}, Env: []string{"BACKUP_SECRET=" + secret}},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func runTarGzExtractToDir(cmdMgr *cmd.CommandHelper, src, dst string) error {
|
||||
return cmdMgr.Run("tar", "-zxvf", src, "-C", dst)
|
||||
}
|
||||
|
||||
func runTarGzDecryptToDir(cmdMgr *cmd.CommandHelper, src, dst, secret string, withSalt bool) error {
|
||||
opensslArgs := []string{"enc", "-d", "-aes-256-cbc"}
|
||||
if withSalt {
|
||||
opensslArgs = append(opensslArgs, "-salt")
|
||||
}
|
||||
opensslArgs = append(opensslArgs, "-pass", "env:BACKUP_SECRET", "-in", src)
|
||||
_, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "openssl", Args: opensslArgs, Env: []string{"BACKUP_SECRET=" + secret}},
|
||||
cmd.PipeCommand{Name: "tar", Args: []string{"-zxf", "-", "-C", dst}},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (z X7zArchiver) Extract(ctx context.Context, filePath, dstDir string, _ str
|
||||
if err := checkCmdAvailability("7z"); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).RunBashCf("7z x -y -o%q %q", dstDir, filePath)
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).Run("7z", "x", "-y", "-o"+dstDir, filePath)
|
||||
}
|
||||
|
||||
func (z X7zArchiver) Compress(ctx context.Context, sourcePaths []string, dstFile string, _ string) (err error) {
|
||||
|
||||
@@ -24,7 +24,7 @@ func (z ZipArchiver) Extract(ctx context.Context, filePath, dstDir string, secre
|
||||
if err := checkCmdAvailability("unzip"); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).RunBashCf("unzip -qo %s -d %s", filePath, dstDir)
|
||||
return cmd.NewCommandMgr(cmd.WithContext(ctx)).Run("unzip", "-qo", filePath, "-d", dstDir)
|
||||
}
|
||||
|
||||
func (z ZipArchiver) Compress(ctx context.Context, sourcePaths []string, dstFile string, _ string) error {
|
||||
|
||||
@@ -77,17 +77,16 @@ func UpdatePingStatus(enable string) error {
|
||||
const panelSysctlPath = "/etc/sysctl.d/98-onepanel.conf"
|
||||
|
||||
var targetPath string
|
||||
var applyCmd string
|
||||
applyArgs := []string{"-p"}
|
||||
|
||||
if _, err := os.Stat(confPath); os.IsNotExist(err) {
|
||||
targetPath = panelSysctlPath
|
||||
applyCmd = fmt.Sprintf("%s sysctl --system", cmd.SudoHandleCmd())
|
||||
if err := cmd.RunDefaultBashCf("%s mkdir -p /etc/sysctl.d", cmd.SudoHandleCmd()); err != nil {
|
||||
applyArgs = []string{"--system"}
|
||||
if err := cmd.NewCommandMgr().RunWithOptionalSudo("mkdir", "-p", "/etc/sysctl.d"); err != nil {
|
||||
return fmt.Errorf("failed to create directory /etc/sysctl.d: %v", err)
|
||||
}
|
||||
} else {
|
||||
targetPath = confPath
|
||||
applyCmd = fmt.Sprintf("%s sysctl -p", cmd.SudoHandleCmd())
|
||||
}
|
||||
|
||||
lineBytes, err := os.ReadFile(targetPath)
|
||||
@@ -95,14 +94,14 @@ func UpdatePingStatus(enable string) error {
|
||||
return fmt.Errorf("failed to read %s: %v", targetPath, err)
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashCf("echo %s | %s tee /proc/sys/net/ipv4/icmp_echo_ignore_all > /dev/null", enable, cmd.SudoHandleCmd()); err != nil {
|
||||
if err := cmd.WriteFileWithOptionalSudo("/proc/sys/net/ipv4/icmp_echo_ignore_all", []byte(enable), constant.FilePerm); err != nil {
|
||||
return fmt.Errorf("failed to apply ipv4 ping status temporarily: %v", err)
|
||||
}
|
||||
|
||||
var hasIpv6 bool
|
||||
if _, err := os.Stat("/proc/sys/net/ipv6/icmp/echo_ignore_all"); err == nil {
|
||||
hasIpv6 = true
|
||||
if err := cmd.RunDefaultBashCf("echo %s | %s tee /proc/sys/net/ipv6/icmp/echo_ignore_all > /dev/null", enable, cmd.SudoHandleCmd()); err != nil {
|
||||
if err := cmd.WriteFileWithOptionalSudo("/proc/sys/net/ipv6/icmp/echo_ignore_all", []byte(enable), constant.FilePerm); err != nil {
|
||||
global.LOG.Warnf("failed to apply ipv6 ping status temporarily: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -136,18 +135,12 @@ func UpdatePingStatus(enable string) error {
|
||||
newFiles = append(newFiles, "net.ipv6.icmp.echo_ignore_all="+enable)
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, constant.FilePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open %s: %v", targetPath, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err = file.WriteString(strings.Join(newFiles, "\n")); err != nil {
|
||||
if err = cmd.WriteFileWithOptionalSudo(targetPath, []byte(strings.Join(newFiles, "\n")), constant.FilePerm); err != nil {
|
||||
return fmt.Errorf("failed to write to %s: %v", targetPath, err)
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashC(applyCmd); err != nil {
|
||||
global.LOG.Warnf("failed to apply persistent config with '%s': %v", applyCmd, err)
|
||||
if err := cmd.NewCommandMgr().RunWithOptionalSudo("sysctl", applyArgs...); err != nil {
|
||||
global.LOG.Warnf("failed to apply persistent config: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -22,12 +22,12 @@ func (f *Firewall) Name() string {
|
||||
}
|
||||
|
||||
func (f *Firewall) Status() (bool, error) {
|
||||
stdout, _ := cmd.RunDefaultWithStdoutBashC("LANGUAGE=en_US:en firewall-cmd --state")
|
||||
stdout, _ := cmd.NewCommandMgr(cmd.WithEnv("LANGUAGE=en_US:en")).RunWithStdout("firewall-cmd", "--state")
|
||||
return stdout == "running\n", nil
|
||||
}
|
||||
|
||||
func (f *Firewall) Version() (string, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("LANGUAGE=en_US:en firewall-cmd --version")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithEnv("LANGUAGE=en_US:en")).RunWithStdout("firewall-cmd", "--version")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("load the firewall version failed, %v", err)
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func (f *Firewall) Restart() error {
|
||||
}
|
||||
|
||||
func (f *Firewall) Reload() error {
|
||||
if err := cmd.RunDefaultBashC("firewall-cmd --reload"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("firewall-cmd", "--reload"); err != nil {
|
||||
return fmt.Errorf("reload firewall failed, err: %v", err)
|
||||
}
|
||||
return nil
|
||||
@@ -68,7 +68,7 @@ func (f *Firewall) ListPort() ([]FireInfo, error) {
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("firewall-cmd --zone=public --list-ports")
|
||||
stdout, err := cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--list-ports")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func (f *Firewall) ListPort() ([]FireInfo, error) {
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
stdout1, err := cmd.RunDefaultWithStdoutBashC("firewall-cmd --zone=public --list-rich-rules")
|
||||
stdout1, err := cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--list-rich-rules")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (f *Firewall) ListForward() ([]FireInfo, error) {
|
||||
if err := f.EnableForward(); err != nil {
|
||||
global.LOG.Errorf("init port forward failed, err: %v", err)
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("firewall-cmd --zone=public --list-forward-ports")
|
||||
stdout, err := cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--list-forward-ports")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -137,7 +137,7 @@ func (f *Firewall) ListForward() ([]FireInfo, error) {
|
||||
}
|
||||
|
||||
func (f *Firewall) ListAddress() ([]FireInfo, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("firewall-cmd --zone=public --list-rich-rules")
|
||||
stdout, err := cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--list-rich-rules")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (f *Firewall) Port(port FireInfo, operation string) error {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashCf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("firewall-cmd", "--zone=public", "--"+operation+"-port="+port.Port+"/"+port.Protocol, "--permanent"); err != nil {
|
||||
return fmt.Errorf("%s (port: %s/%s strategy: %s) failed, %v", operation, port.Port, port.Protocol, port.Strategy, err)
|
||||
}
|
||||
return nil
|
||||
@@ -184,12 +184,13 @@ func (f *Firewall) RichRules(rule FireInfo, operation string) error {
|
||||
ruleStr += fmt.Sprintf("protocol=%s ", rule.Protocol)
|
||||
}
|
||||
ruleStr += rule.Strategy
|
||||
if err := cmd.RunDefaultBashCf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent", operation, ruleStr); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("firewall-cmd", "--zone=public", "--"+operation+"-rich-rule", ruleStr, "--permanent"); err != nil {
|
||||
return fmt.Errorf("%s rich rules (%s) failed, %v", operation, ruleStr, err)
|
||||
}
|
||||
if len(rule.Address) == 0 {
|
||||
if err := cmd.RunDefaultBashCf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent", operation, strings.ReplaceAll(ruleStr, "family=ipv4 ", "family=ipv6 ")); err != nil {
|
||||
return fmt.Errorf("%s rich rules (%s) failed, %v", operation, strings.ReplaceAll(ruleStr, "family=ipv4 ", "family=ipv6 "), err)
|
||||
ipv6Rule := strings.ReplaceAll(ruleStr, "family=ipv4 ", "family=ipv6 ")
|
||||
if err := cmd.NewCommandMgr().Run("firewall-cmd", "--zone=public", "--"+operation+"-rich-rule", ipv6Rule, "--permanent"); err != nil {
|
||||
return fmt.Errorf("%s rich rules (%s) failed, %v", operation, ipv6Rule, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -199,12 +200,12 @@ func (f *Firewall) PortForward(info Forward, operation string) error {
|
||||
if cmd.CheckIllegal(operation, info.Port, info.Protocol, info.TargetIP, info.TargetPort) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
ruleStr := fmt.Sprintf("firewall-cmd --zone=public --%s-forward-port=port=%s:proto=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.TargetPort)
|
||||
forwardRule := fmt.Sprintf("--%s-forward-port=port=%s:proto=%s:toport=%s", operation, info.Port, info.Protocol, info.TargetPort)
|
||||
if info.TargetIP != "" && info.TargetIP != "127.0.0.1" && info.TargetIP != "localhost" {
|
||||
ruleStr = fmt.Sprintf("firewall-cmd --zone=public --%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.TargetIP, info.TargetPort)
|
||||
forwardRule = fmt.Sprintf("--%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s", operation, info.Port, info.Protocol, info.TargetIP, info.TargetPort)
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashC(ruleStr); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("firewall-cmd", "--zone=public", forwardRule, "--permanent"); err != nil {
|
||||
return fmt.Errorf("%s port forward failed, %s", operation, err)
|
||||
}
|
||||
if err := f.Reload(); err != nil {
|
||||
@@ -236,10 +237,10 @@ func (f *Firewall) loadInfo(line string) FireInfo {
|
||||
}
|
||||
|
||||
func (f *Firewall) EnableForward() error {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("firewall-cmd --zone=public --query-masquerade")
|
||||
stdout, err := cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--query-masquerade")
|
||||
if err != nil {
|
||||
if strings.HasSuffix(strings.TrimSpace(stdout), "no") {
|
||||
if err := cmd.RunDefaultBashC("firewall-cmd --zone=public --add-masquerade --permanent"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("firewall-cmd", "--zone=public", "--add-masquerade", "--permanent"); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.Reload()
|
||||
|
||||
@@ -2,8 +2,10 @@ package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -22,11 +24,12 @@ func (i *Iptables) Name() string {
|
||||
}
|
||||
|
||||
func (i *Iptables) Status() (bool, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("iptables -L -n | head -1")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("iptables", "-L", "-n")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.Contains(stdout, "Chain"), nil
|
||||
firstLine := strings.Split(strings.TrimSpace(stdout), "\n")[0]
|
||||
return strings.Contains(firstLine, "Chain"), nil
|
||||
}
|
||||
|
||||
func (i *Iptables) Start() error {
|
||||
@@ -46,7 +49,7 @@ func (i *Iptables) Reload() error {
|
||||
}
|
||||
|
||||
func (i *Iptables) Version() (string, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("iptables --version")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("iptables", "--version")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get iptables version: %w", err)
|
||||
}
|
||||
@@ -131,15 +134,13 @@ func (i *Iptables) Port(port FireInfo, operation string) error {
|
||||
action = "DROP"
|
||||
}
|
||||
|
||||
ruleArgs := []string{fmt.Sprintf("-p %s", protocol)}
|
||||
ruleArgs = append(ruleArgs, fmt.Sprintf("--dport %s", portSpec), fmt.Sprintf("-j %s", action))
|
||||
ruleSpec := strings.Join(ruleArgs, " ")
|
||||
ruleArgs := []string{"-p", protocol, "--dport", portSpec, "-j", action}
|
||||
if operation == "add" {
|
||||
if err := iptables.AddRule(iptables.FilterTab, port.Chain, ruleSpec); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, port.Chain, ruleArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := iptables.DeleteRule(iptables.FilterTab, port.Chain, ruleSpec); err != nil {
|
||||
if err := iptables.DeleteRule(iptables.FilterTab, port.Chain, ruleArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -174,7 +175,7 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error {
|
||||
|
||||
var ruleArgs []string
|
||||
if address != "" {
|
||||
ruleArgs = append(ruleArgs, fmt.Sprintf("-s %s", address))
|
||||
ruleArgs = append(ruleArgs, "-s", address)
|
||||
}
|
||||
|
||||
protocol := strings.TrimSpace(rule.Protocol)
|
||||
@@ -183,7 +184,7 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error {
|
||||
}
|
||||
|
||||
if protocol != "" {
|
||||
ruleArgs = append(ruleArgs, fmt.Sprintf("-p %s", protocol))
|
||||
ruleArgs = append(ruleArgs, "-p", protocol)
|
||||
}
|
||||
|
||||
if rule.Port != "" {
|
||||
@@ -194,17 +195,16 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error {
|
||||
if protocol == "" {
|
||||
return fmt.Errorf("protocol is required when specifying a port")
|
||||
}
|
||||
ruleArgs = append(ruleArgs, fmt.Sprintf("--dport %s", portSegment))
|
||||
ruleArgs = append(ruleArgs, "--dport", portSegment)
|
||||
}
|
||||
|
||||
ruleArgs = append(ruleArgs, fmt.Sprintf("-j %s", action))
|
||||
ruleSpec := strings.Join(ruleArgs, " ")
|
||||
ruleArgs = append(ruleArgs, "-j", action)
|
||||
if operation == "add" {
|
||||
if err := iptables.AddRule(iptables.FilterTab, rule.Chain, ruleSpec); err != nil {
|
||||
if err := iptables.AddRule(iptables.FilterTab, rule.Chain, ruleArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := iptables.DeleteRule(iptables.FilterTab, rule.Chain, ruleSpec); err != nil {
|
||||
if err := iptables.DeleteRule(iptables.FilterTab, rule.Chain, ruleArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -232,11 +232,16 @@ func (i *Iptables) ListForward() ([]FireInfo, error) {
|
||||
}
|
||||
|
||||
func EnableIptablesForward() error {
|
||||
if err := cmd.RunDefaultBashC("echo 1 > /proc/sys/net/ipv4/ip_forward"); err != nil {
|
||||
if err := cmd.WriteFileWithOptionalSudo("/proc/sys/net/ipv4/ip_forward", []byte("1"), 0644); err != nil {
|
||||
return fmt.Errorf("failed to enable IP forwarding: %w", err)
|
||||
}
|
||||
_ = cmd.RunDefaultBashC("grep -q '^net.ipv4.ip_forward' /etc/sysctl.conf || echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf")
|
||||
_ = cmd.RunDefaultBashC("sysctl -p")
|
||||
if data, err := os.ReadFile("/etc/sysctl.conf"); err == nil {
|
||||
if !strings.Contains(string(data), "net.ipv4.ip_forward") {
|
||||
content := strings.TrimRight(string(data), "\n") + "\nnet.ipv4.ip_forward = 1\n"
|
||||
_ = cmd.WriteFileWithOptionalSudo("/etc/sysctl.conf", []byte(content), 0644)
|
||||
}
|
||||
}
|
||||
_ = cmd.NewCommandMgr().RunWithOptionalSudo("sysctl", "-p")
|
||||
|
||||
if err := iptables.AddChainWithAppend(iptables.NatTab, "PREROUTING", iptables.Chain1PanelPreRouting); err != nil {
|
||||
return err
|
||||
|
||||
@@ -24,8 +24,8 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
EstablishedRule = "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'ESTABLISHED Whitelist'"
|
||||
IoRuleIn = "-i lo -j ACCEPT -m comment --comment 'Loopback Whitelist'"
|
||||
EstablishedRule = "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment \"ESTABLISHED Whitelist\""
|
||||
IoRuleIn = "-i lo -j ACCEPT -m comment --comment \"Loopback Whitelist\""
|
||||
DropAllTcp = "-p tcp -j DROP"
|
||||
DropAllUdp = "-p udp -j DROP"
|
||||
AllowSSH = "-p tcp --dport ssh -j ACCEPT"
|
||||
@@ -43,72 +43,91 @@ const (
|
||||
NatTab = "nat"
|
||||
)
|
||||
|
||||
func RunWithStd(tab, rule string) (string, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(60*time.Second))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -w -t %s %s", cmd.SudoHandleCmd(), tab, rule)
|
||||
func runIptables(tab string, ignoreExist1, withWait bool, ruleArgs ...string) (string, error) {
|
||||
options := []cmd.Option{cmd.WithTimeout(60 * time.Second)}
|
||||
if ignoreExist1 {
|
||||
options = append(options, cmd.WithIgnoreExist1())
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(options...)
|
||||
args := []string{"-t", tab}
|
||||
if withWait {
|
||||
args = append(args, "-w")
|
||||
}
|
||||
args = append(args, ruleArgs...)
|
||||
return cmdMgr.RunWithOptionalSudoAndStdout("iptables", args...)
|
||||
}
|
||||
|
||||
func RunWithStd(tab string, args ...string) (string, error) {
|
||||
stdout, err := runIptables(tab, true, true, args...)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("iptables command failed [table=%s, rule=%s]: %v", tab, rule, err)
|
||||
global.LOG.Errorf("iptables command failed [table=%s, args=%s]: %v", tab, strings.Join(args, " "), err)
|
||||
return stdout, err
|
||||
}
|
||||
return stdout, nil
|
||||
}
|
||||
func RunWithoutIgnore(tab, rule string) (string, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(60 * time.Second))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -t %s %s", cmd.SudoHandleCmd(), tab, rule)
|
||||
func RunWithoutIgnore(tab string, args ...string) (string, error) {
|
||||
stdout, err := runIptables(tab, false, false, args...)
|
||||
if err != nil {
|
||||
return stdout, err
|
||||
}
|
||||
return stdout, nil
|
||||
}
|
||||
func Run(tab, rule string) error {
|
||||
if _, err := RunWithStd(tab, rule); err != nil {
|
||||
func Run(tab string, args ...string) error {
|
||||
if _, err := RunWithStd(tab, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewChain(tab, chain string) error {
|
||||
return Run(tab, "-N "+chain)
|
||||
return Run(tab, "-N", chain)
|
||||
}
|
||||
|
||||
func ClearChain(tab, chain string) error {
|
||||
return Run(tab, "-F "+chain)
|
||||
return Run(tab, "-F", chain)
|
||||
}
|
||||
|
||||
func AddRule(tab, chain, rule string) error {
|
||||
if CheckRuleExist(tab, chain, rule) {
|
||||
func AddRule(tab, chain string, ruleArgs ...string) error {
|
||||
if CheckRuleExist(tab, chain, ruleArgs...) {
|
||||
return nil
|
||||
}
|
||||
return Run(tab, fmt.Sprintf("-A %s %s", chain, rule))
|
||||
args := append([]string{"-A", chain}, ruleArgs...)
|
||||
return Run(tab, args...)
|
||||
}
|
||||
func DeleteRule(tab, chain, rule string) error {
|
||||
return Run(tab, fmt.Sprintf("-D %s %s", chain, rule))
|
||||
func DeleteRule(tab, chain string, ruleArgs ...string) error {
|
||||
args := append([]string{"-D", chain}, ruleArgs...)
|
||||
return Run(tab, args...)
|
||||
}
|
||||
|
||||
func CheckChainExist(tab, chain string) (bool, error) {
|
||||
stdout, err := RunWithStd(tab, fmt.Sprintf("-S | grep -w 'N %s'", chain))
|
||||
stdout, err := RunWithStd(tab, "-S")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("check chain %s from tab %s exist failed, err: %v", chain, tab, err)
|
||||
return false, fmt.Errorf("check chain %s from tab %s exist failed, err: %v", chain, tab, err)
|
||||
}
|
||||
if strings.TrimSpace(stdout) == "" {
|
||||
return false, nil
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
if strings.TrimSpace(line) == "-N "+chain {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
return false, nil
|
||||
}
|
||||
func CheckChainBind(tab, parentChain, chain string) (bool, error) {
|
||||
stdout, err := RunWithStd(tab, fmt.Sprintf("-S %s | grep -- '-j %s'", parentChain, chain))
|
||||
stdout, err := RunWithStd(tab, "-S", parentChain)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("check chain %s from tab %s is bind to %s failed, err: %v", chain, tab, parentChain, err)
|
||||
return false, fmt.Errorf("check chain %s from tab %s is bind to %s failed, err: %v", chain, tab, parentChain, err)
|
||||
}
|
||||
if strings.TrimSpace(stdout) == "" {
|
||||
return false, nil
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
if strings.Contains(line, "-j "+chain) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
return false, nil
|
||||
}
|
||||
func CheckRuleExist(tab, chain, rule string) bool {
|
||||
_, err := RunWithoutIgnore(tab, fmt.Sprintf("-C %s %s", chain, rule))
|
||||
func CheckRuleExist(tab, chain string, ruleArgs ...string) bool {
|
||||
args := append([]string{"-C", chain}, ruleArgs...)
|
||||
_, err := RunWithoutIgnore(tab, args...)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@@ -130,7 +149,7 @@ func BindChain(tab, targetChain, chain string, position int) error {
|
||||
return fmt.Errorf("find chain %s number from %s failed, err: %w", chain, targetChain, err)
|
||||
}
|
||||
if line == 0 {
|
||||
if err := Run(tab, fmt.Sprintf("-I %s %d -j %s", targetChain, position, chain)); err != nil {
|
||||
if err := Run(tab, "-I", targetChain, strconv.Itoa(position), "-j", chain); err != nil {
|
||||
return fmt.Errorf("bind chain %s to %s failed, err: %w", chain, targetChain, err)
|
||||
}
|
||||
}
|
||||
@@ -142,13 +161,18 @@ func UnbindChain(tab, targetChain, chain string) error {
|
||||
return fmt.Errorf("find chain %s number from %s failed, err: %w", chain, targetChain, err)
|
||||
}
|
||||
if line != 0 {
|
||||
return Run(tab, fmt.Sprintf("-D %s %v", targetChain, line))
|
||||
return Run(tab, "-D", targetChain, strconv.Itoa(line))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindChainNum(tab, targetChain, chain string) (int, error) {
|
||||
stdout, err := RunWithStd(tab, fmt.Sprintf("-L %s --line-numbers -n | grep -w %s", targetChain, chain))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(60*time.Second))
|
||||
commandName, commandArgs := cmd.WrapWithOptionalSudo("iptables", "-w", "-t", tab, "-L", targetChain, "--line-numbers", "-n")
|
||||
stdout, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: commandName, Args: commandArgs},
|
||||
cmd.PipeCommand{Name: "grep", Args: []string{"-w", chain}},
|
||||
)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to list rules in chain %s: %w", targetChain, err)
|
||||
}
|
||||
@@ -190,5 +214,5 @@ func AddChainWithAppend(tab, parentChain, chain string) error {
|
||||
return nil
|
||||
}
|
||||
func AppendChain(tab string, parentChain, chain string) error {
|
||||
return Run(tab, fmt.Sprintf("-A %s -j %s", parentChain, chain))
|
||||
return Run(tab, "-A", parentChain, "-j", chain)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package iptables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -26,47 +26,47 @@ func AddFilterRule(chain string, policy FilterRules) error {
|
||||
if err := validateRuleSafety(policy, chain); err != nil {
|
||||
return err
|
||||
}
|
||||
iptablesArg := fmt.Sprintf("-A %s", chain)
|
||||
args := []string{"-A", chain}
|
||||
if policy.Protocol != "" {
|
||||
iptablesArg += fmt.Sprintf(" -p %s", policy.Protocol)
|
||||
args = append(args, "-p", policy.Protocol)
|
||||
}
|
||||
if len(policy.SrcPort) != 0 {
|
||||
iptablesArg += fmt.Sprintf(" --sport %s", policy.SrcPort)
|
||||
args = append(args, "--sport", policy.SrcPort)
|
||||
}
|
||||
if len(policy.DstPort) != 0 {
|
||||
iptablesArg += fmt.Sprintf(" --dport %s", policy.DstPort)
|
||||
args = append(args, "--dport", policy.DstPort)
|
||||
}
|
||||
if policy.SrcIP != "" {
|
||||
iptablesArg += fmt.Sprintf(" -s %s", policy.SrcIP)
|
||||
args = append(args, "-s", policy.SrcIP)
|
||||
}
|
||||
if policy.DstIP != "" {
|
||||
iptablesArg += fmt.Sprintf(" -d %s", policy.DstIP)
|
||||
args = append(args, "-d", policy.DstIP)
|
||||
}
|
||||
iptablesArg += fmt.Sprintf(" -j %s", policy.Strategy)
|
||||
args = append(args, "-j", policy.Strategy)
|
||||
|
||||
return Run(FilterTab, iptablesArg)
|
||||
return Run(FilterTab, args...)
|
||||
}
|
||||
|
||||
func DeleteFilterRule(chain string, policy FilterRules) error {
|
||||
iptablesArg := fmt.Sprintf("-D %s", chain)
|
||||
args := []string{"-D", chain}
|
||||
if policy.Protocol != "" {
|
||||
iptablesArg += fmt.Sprintf(" -p %s", policy.Protocol)
|
||||
args = append(args, "-p", policy.Protocol)
|
||||
}
|
||||
if len(policy.SrcPort) != 0 {
|
||||
iptablesArg += fmt.Sprintf(" --sport %s", policy.SrcPort)
|
||||
args = append(args, "--sport", policy.SrcPort)
|
||||
}
|
||||
if len(policy.DstPort) != 0 {
|
||||
iptablesArg += fmt.Sprintf(" --dport %s", policy.DstPort)
|
||||
args = append(args, "--dport", policy.DstPort)
|
||||
}
|
||||
if policy.SrcIP != "" {
|
||||
iptablesArg += fmt.Sprintf(" -s %s", policy.SrcIP)
|
||||
args = append(args, "-s", policy.SrcIP)
|
||||
}
|
||||
if policy.DstIP != "" {
|
||||
iptablesArg += fmt.Sprintf(" -d %s", policy.DstIP)
|
||||
args = append(args, "-d", policy.DstIP)
|
||||
}
|
||||
iptablesArg += fmt.Sprintf(" -j %s", policy.Strategy)
|
||||
args = append(args, "-j", policy.Strategy)
|
||||
|
||||
return Run(FilterTab, iptablesArg)
|
||||
return Run(FilterTab, args...)
|
||||
}
|
||||
|
||||
func ReadFilterRulesByChain(chain string) ([]FilterRules, error) {
|
||||
@@ -74,8 +74,7 @@ func ReadFilterRulesByChain(chain string) ([]FilterRules, error) {
|
||||
if cmd.CheckIllegal(chain) {
|
||||
return rules, buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(20*time.Second))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -w -t %s -nL %s", cmd.SudoHandleCmd(), FilterTab, chain)
|
||||
stdout, err := RunWithStd(FilterTab, "-nL", chain)
|
||||
if err != nil {
|
||||
return rules, fmt.Errorf("load filter fules by chain %s failed, %v", chain, err)
|
||||
}
|
||||
@@ -107,8 +106,7 @@ func LoadDefaultStrategy(chain string) (string, error) {
|
||||
if cmd.CheckIllegal(chain) {
|
||||
return "", buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(20*time.Second))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -w -t %s -L %s", cmd.SudoHandleCmd(), FilterTab, chain)
|
||||
stdout, err := RunWithStd(FilterTab, "-L", chain)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("load filter fules by chain %s failed, %v", chain, err)
|
||||
}
|
||||
@@ -170,12 +168,12 @@ func LoadInitStatus(clientName, tab string) (bool, bool) {
|
||||
}
|
||||
return checkWithInitAndBind(initRules, bindRules, lines)
|
||||
case "forward":
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("cat /proc/sys/net/ipv4/ip_forward")
|
||||
data, err := os.ReadFile("/proc/sys/net/ipv4/ip_forward")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("check /proc/sys/net/ipv4/ip_forward failed, err: %v", err)
|
||||
return false, false
|
||||
}
|
||||
if strings.TrimSpace(stdout) == "0" {
|
||||
if strings.TrimSpace(string(data)) == "0" {
|
||||
return false, false
|
||||
}
|
||||
natRules, err := RunWithStd(NatTab, "-S")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -9,33 +8,33 @@ func AddForward(protocol, srcPort, dest, destPort, iface string, save bool) erro
|
||||
srcPort = strings.ReplaceAll(srcPort, "-", ":")
|
||||
itemDstPort := strings.ReplaceAll(destPort, "-", ":")
|
||||
if dest != "" && dest != "127.0.0.1" && dest != "localhost" {
|
||||
iptablesArg := fmt.Sprintf("-A %s", Chain1PanelPreRouting)
|
||||
args := []string{"-A", Chain1PanelPreRouting}
|
||||
if iface != "" {
|
||||
iptablesArg += fmt.Sprintf(" -i %s", iface)
|
||||
args = append(args, "-i", iface)
|
||||
}
|
||||
iptablesArg += fmt.Sprintf(" -p %s --dport %s -j DNAT --to-destination %s:%s", protocol, srcPort, dest, destPort)
|
||||
if err := Run(NatTab, iptablesArg); err != nil {
|
||||
args = append(args, "-p", protocol, "--dport", srcPort, "-j", "DNAT", "--to-destination", dest+":"+destPort)
|
||||
if err := Run(NatTab, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Run(NatTab, fmt.Sprintf("-A %s -d %s -p %s --dport %s -j MASQUERADE", Chain1PanelPostRouting, dest, protocol, itemDstPort)); err != nil {
|
||||
if err := Run(NatTab, "-A", Chain1PanelPostRouting, "-d", dest, "-p", protocol, "--dport", itemDstPort, "-j", "MASQUERADE"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Run(FilterTab, fmt.Sprintf("-A %s -d %s -p %s --dport %s -j ACCEPT", Chain1PanelForward, dest, protocol, itemDstPort)); err != nil {
|
||||
if err := Run(FilterTab, "-A", Chain1PanelForward, "-d", dest, "-p", protocol, "--dport", itemDstPort, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Run(FilterTab, fmt.Sprintf("-A %s -s %s -p %s --sport %s -j ACCEPT", Chain1PanelForward, dest, protocol, itemDstPort)); err != nil {
|
||||
if err := Run(FilterTab, "-A", Chain1PanelForward, "-s", dest, "-p", protocol, "--sport", itemDstPort, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
iptablesArg := fmt.Sprintf("-A %s", Chain1PanelPreRouting)
|
||||
args := []string{"-A", Chain1PanelPreRouting}
|
||||
if iface != "" {
|
||||
iptablesArg += fmt.Sprintf(" -i %s", iface)
|
||||
args = append(args, "-i", iface)
|
||||
}
|
||||
iptablesArg += fmt.Sprintf(" -p %s --dport %s -j REDIRECT --to-port %s", protocol, srcPort, destPort)
|
||||
if err := Run(NatTab, iptablesArg); err != nil {
|
||||
args = append(args, "-p", protocol, "--dport", srcPort, "-j", "REDIRECT", "--to-port", destPort)
|
||||
if err := Run(NatTab, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -44,20 +43,20 @@ func AddForward(protocol, srcPort, dest, destPort, iface string, save bool) erro
|
||||
|
||||
func DeleteForward(num string, protocol, srcPort, dest, destPort, iface string) error {
|
||||
itemDstPort := strings.ReplaceAll(destPort, "-", ":")
|
||||
if err := Run(NatTab, fmt.Sprintf("-D %s %s", Chain1PanelPreRouting, num)); err != nil {
|
||||
if err := Run(NatTab, "-D", Chain1PanelPreRouting, num); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dest != "" && dest != "127.0.0.1" && dest != "localhost" {
|
||||
if err := Run(NatTab, fmt.Sprintf("-D %s -d %s -p %s --dport %s -j MASQUERADE", Chain1PanelPostRouting, dest, protocol, itemDstPort)); err != nil {
|
||||
if err := Run(NatTab, "-D", Chain1PanelPostRouting, "-d", dest, "-p", protocol, "--dport", itemDstPort, "-j", "MASQUERADE"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Run(FilterTab, fmt.Sprintf("-D %s -d %s -p %s --dport %s -j ACCEPT", Chain1PanelForward, dest, protocol, itemDstPort)); err != nil {
|
||||
if err := Run(FilterTab, "-D", Chain1PanelForward, "-d", dest, "-p", protocol, "--dport", itemDstPort, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Run(FilterTab, fmt.Sprintf("-D %s -s %s -p %s --sport %s -j ACCEPT", Chain1PanelForward, dest, protocol, itemDstPort)); err != nil {
|
||||
if err := Run(FilterTab, "-D", Chain1PanelForward, "-s", dest, "-p", protocol, "--sport", itemDstPort, "-j", "ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -68,7 +67,7 @@ func ListForward(chain ...string) ([]IptablesNatInfo, error) {
|
||||
if len(chain) == 0 {
|
||||
chain = append(chain, Chain1PanelPreRouting)
|
||||
}
|
||||
stdout, err := RunWithStd(NatTab, fmt.Sprintf("-nvL %s --line-numbers", chain[0]))
|
||||
stdout, err := RunWithStd(NatTab, "-nvL", chain[0], "--line-numbers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ package iptables
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,7 +26,7 @@ const (
|
||||
func SaveRulesToFile(tab, chain, fileName string) error {
|
||||
rulesFile := path.Join(global.Dir.FirewallDir, fileName)
|
||||
|
||||
stdout, err := RunWithStd(tab, fmt.Sprintf("-S %s", chain))
|
||||
stdout, err := RunWithStd(tab, "-S", chain)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list %s rules: %w", chain, err)
|
||||
}
|
||||
@@ -80,7 +82,7 @@ func LoadRulesFromFile(tab, chain, fileName string) error {
|
||||
|
||||
for _, rule := range rules {
|
||||
if strings.HasPrefix(rule, fmt.Sprintf("-A %s", chain)) {
|
||||
if err := Run(tab, rule); err != nil {
|
||||
if err := restoreRule(tab, rule); err != nil {
|
||||
global.LOG.Errorf("apply rule '%s' failed, err: %v", rule, err)
|
||||
}
|
||||
}
|
||||
@@ -88,3 +90,14 @@ func LoadRulesFromFile(tab, chain, fileName string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func restoreRule(tab, rule string) error {
|
||||
restoreInput := fmt.Sprintf("*%s\n%s\nCOMMIT\n", tab, rule)
|
||||
commandName, commandArgs := cmd.WrapWithOptionalSudo("iptables-restore", "-n")
|
||||
_, err := cmd.NewCommandMgr().RunPipe(cmd.PipeCommand{
|
||||
Name: commandName,
|
||||
Args: commandArgs,
|
||||
Stdin: bytes.NewReader([]byte(restoreInput)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
@@ -24,35 +25,34 @@ func (f *Ufw) Name() string {
|
||||
}
|
||||
|
||||
func (f *Ufw) Status() (bool, error) {
|
||||
stdout, _ := cmd.RunDefaultWithStdoutBashCf("%s status | grep Status", f.CmdStr)
|
||||
if stdout == "Status: active\n" {
|
||||
stdout, _ := f.runWithStdout("status")
|
||||
if strings.Contains(stdout, "Status: active") {
|
||||
return true, nil
|
||||
}
|
||||
stdout1, _ := cmd.RunDefaultWithStdoutBashCf("%s status | grep 状态", f.CmdStr)
|
||||
if stdout1 == "状态: 激活\n" {
|
||||
if strings.Contains(stdout, "状态: 激活") {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (f *Ufw) Version() (string, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s version | grep ufw", f.CmdStr)
|
||||
stdout, err := f.runWithStdout("version")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("load the firewall status failed, %v", err)
|
||||
}
|
||||
info := strings.ReplaceAll(stdout, "\n", "")
|
||||
info := strings.Split(strings.TrimSpace(stdout), "\n")[0]
|
||||
return strings.ReplaceAll(info, "ufw ", ""), nil
|
||||
}
|
||||
|
||||
func (f *Ufw) Start() error {
|
||||
if err := cmd.RunDefaultBashCf("echo y | %s enable", f.CmdStr); err != nil {
|
||||
if err := f.run("--force", "enable"); err != nil {
|
||||
return fmt.Errorf("enable the firewall failed, %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Ufw) Stop() error {
|
||||
if err := cmd.RunDefaultBashCf("%s disable", f.CmdStr); err != nil {
|
||||
if err := f.run("disable"); err != nil {
|
||||
return fmt.Errorf("stop the firewall failed, %v", err)
|
||||
}
|
||||
return nil
|
||||
@@ -73,7 +73,7 @@ func (f *Ufw) Reload() error {
|
||||
}
|
||||
|
||||
func (f *Ufw) ListPort() ([]FireInfo, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s status verbose", f.CmdStr)
|
||||
stdout, err := f.runWithStdout("status", "verbose")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func (f *Ufw) ListPort() ([]FireInfo, error) {
|
||||
}
|
||||
|
||||
func (f *Ufw) ListAddress() ([]FireInfo, error) {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s status verbose", f.CmdStr)
|
||||
stdout, err := f.runWithStdout("status", "verbose")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -141,15 +141,15 @@ func (f *Ufw) Port(port FireInfo, operation string) error {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
|
||||
command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port)
|
||||
args := []string{port.Strategy, port.Port}
|
||||
if operation == "remove" {
|
||||
command = fmt.Sprintf("%s delete %s %s", f.CmdStr, port.Strategy, port.Port)
|
||||
args = []string{"delete", port.Strategy, port.Port}
|
||||
}
|
||||
if len(port.Protocol) != 0 {
|
||||
command += fmt.Sprintf("/%s", port.Protocol)
|
||||
args[len(args)-1] += "/" + port.Protocol
|
||||
}
|
||||
if err := cmd.RunDefaultBashC(command); err != nil {
|
||||
return fmt.Errorf("%s (%s) failed, %v", operation, command, err)
|
||||
if err := f.run(args...); err != nil {
|
||||
return fmt.Errorf("%s (%s) failed, %v", operation, strings.Join(args, " "), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -169,31 +169,36 @@ func (f *Ufw) RichRules(rule FireInfo, operation string) error {
|
||||
}
|
||||
|
||||
insertNum := f.loadInsertNum(rule, operation)
|
||||
ruleStr := fmt.Sprintf("%s insert %d %s ", f.CmdStr, insertNum, rule.Strategy)
|
||||
args := []string{"insert", strconv.Itoa(insertNum), rule.Strategy}
|
||||
if operation == "remove" {
|
||||
ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy)
|
||||
args = []string{"delete", rule.Strategy}
|
||||
}
|
||||
if len(rule.Protocol) != 0 {
|
||||
ruleStr += fmt.Sprintf("proto %s ", rule.Protocol)
|
||||
args = append(args, "proto", rule.Protocol)
|
||||
}
|
||||
if strings.Contains(rule.Address, "-") {
|
||||
ruleStr += fmt.Sprintf("from %s to %s ", strings.Split(rule.Address, "-")[0], strings.Split(rule.Address, "-")[1])
|
||||
parts := strings.Split(rule.Address, "-")
|
||||
args = append(args, "from", parts[0], "to", parts[1])
|
||||
} else {
|
||||
ruleStr += fmt.Sprintf("from %s ", rule.Address)
|
||||
args = append(args, "from", rule.Address)
|
||||
}
|
||||
if len(rule.Port) != 0 {
|
||||
ruleStr += fmt.Sprintf("to any port %s ", rule.Port)
|
||||
args = append(args, "to", "any", "port", rule.Port)
|
||||
}
|
||||
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC(ruleStr)
|
||||
stdout, err := f.runWithStdout(args...)
|
||||
if err != nil {
|
||||
if strings.Contains(stdout, "ERROR: Invalid position") || strings.Contains(stdout, "ERROR: 无效位置") {
|
||||
if err := cmd.RunDefaultBashC(strings.ReplaceAll(ruleStr, "insert 1 ", "")); err != nil {
|
||||
return fmt.Errorf("%s rich rules (%s), failed, %v", operation, ruleStr, err)
|
||||
fallbackArgs := args
|
||||
if len(args) >= 2 && args[0] == "insert" {
|
||||
fallbackArgs = append([]string{}, args[2:]...)
|
||||
}
|
||||
if err := f.run(fallbackArgs...); err != nil {
|
||||
return fmt.Errorf("%s rich rules (%s), failed, %v", operation, strings.Join(args, " "), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("%s rich rules (%s), failed, %v", operation, ruleStr, err)
|
||||
return fmt.Errorf("%s rich rules (%s), failed, %v", operation, strings.Join(args, " "), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -259,7 +264,7 @@ func (f *Ufw) loadInsertNum(rule FireInfo, operation string) int {
|
||||
if !strings.Contains(rule.Address, ":") || operation == "remove" {
|
||||
return 1
|
||||
}
|
||||
rules, err := cmd.RunDefaultWithStdoutBashCf("%s status numbered", f.CmdStr)
|
||||
rules, err := f.runWithStdout("status", "numbered")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load ufw rules failed, err: %v", err)
|
||||
return 1
|
||||
@@ -277,3 +282,13 @@ func (f *Ufw) loadInsertNum(rule FireInfo, operation string) int {
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (f *Ufw) run(args ...string) error {
|
||||
_, err := f.runWithStdout(args...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *Ufw) runWithStdout(args ...string) (string, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithEnv("LANGUAGE=en_US:en"))
|
||||
return cmdMgr.RunWithOptionalSudoAndStdout("ufw", args...)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"errors"
|
||||
@@ -16,6 +15,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
)
|
||||
@@ -229,11 +229,6 @@ func (r *Local) Backup(info BackupInfo) error {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err)
|
||||
}
|
||||
}
|
||||
outfile, err := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, constant.DirPerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err)
|
||||
}
|
||||
defer func() { _ = outfile.Close() }()
|
||||
dumpCmd := "mysqldump"
|
||||
if r.Type == constant.AppMariaDB {
|
||||
dumpCmd = "mariadb-dump"
|
||||
@@ -250,19 +245,13 @@ func (r *Local) Backup(info BackupInfo) error {
|
||||
args = append(args, arg)
|
||||
}
|
||||
args = append(args, info.Name)
|
||||
cmd := exec.Command("docker", args...)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
gzipCmd := exec.Command("gzip", "-cf")
|
||||
gzipCmd.Stdin, _ = cmd.StdoutPipe()
|
||||
gzipCmd.Stdout = outfile
|
||||
_ = gzipCmd.Start()
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("handle backup database failed, err: %v", stderr.String())
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithOutputFile(path.Join(info.TargetDir, info.FileName)))
|
||||
if _, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "docker", Args: args},
|
||||
cmd.PipeCommand{Name: "gzip", Args: []string{"-cf"}},
|
||||
); err != nil {
|
||||
return fmt.Errorf("handle backup database failed, err: %v", err)
|
||||
}
|
||||
_ = gzipCmd.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"database/sql"
|
||||
@@ -244,11 +243,6 @@ func (r *Remote) Backup(info BackupInfo) error {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err)
|
||||
}
|
||||
}
|
||||
outfile, err := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, constant.DirPerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err)
|
||||
}
|
||||
defer func() { _ = outfile.Close() }()
|
||||
dumpCmd := "mysqldump"
|
||||
if r.Type == constant.AppMariaDB {
|
||||
dumpCmd = "mariadb-dump"
|
||||
@@ -268,23 +262,32 @@ func (r *Remote) Backup(info BackupInfo) error {
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
||||
backupCmd := fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c '%s %s -h %s -P %d -u%s -p%s %s --default-character-set=%s %s'",
|
||||
image, dumpCmd, strings.Join(args, " "), r.Address, r.Port, r.User, r.Password, sslSkip(info.Version, r.Type), info.Format, info.Name)
|
||||
|
||||
global.LOG.Debug(strings.ReplaceAll(backupCmd, r.Password, "******"))
|
||||
cmd := exec.Command("bash", "-c", backupCmd)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
gzipCmd := exec.Command("gzip", "-cf")
|
||||
gzipCmd.Stdin, _ = cmd.StdoutPipe()
|
||||
gzipCmd.Stdout = outfile
|
||||
|
||||
_ = gzipCmd.Start()
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("handle backup database failed, err: %v", stderr.String())
|
||||
backupArgs := []string{"run", "--rm", "--net=host", "-i", image, dumpCmd}
|
||||
backupArgs = append(backupArgs, args...)
|
||||
backupArgs = append(
|
||||
backupArgs,
|
||||
"-h", r.Address,
|
||||
"-P", fmt.Sprintf("%d", r.Port),
|
||||
"-u"+r.User,
|
||||
"-p"+r.Password,
|
||||
sslSkip(info.Version, r.Type),
|
||||
"--default-character-set="+info.Format,
|
||||
info.Name,
|
||||
)
|
||||
debugArgs := append([]string{}, backupArgs...)
|
||||
for i, arg := range debugArgs {
|
||||
if strings.Contains(arg, r.Password) {
|
||||
debugArgs[i] = strings.ReplaceAll(arg, r.Password, "******")
|
||||
}
|
||||
}
|
||||
global.LOG.Debug("docker " + strings.Join(debugArgs, " "))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithOutputFile(path.Join(info.TargetDir, info.FileName)))
|
||||
if _, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "docker", Args: backupArgs},
|
||||
cmd.PipeCommand{Name: "gzip", Args: []string{"-cf"}},
|
||||
); err != nil {
|
||||
return fmt.Errorf("handle backup database failed, err: %v", err)
|
||||
}
|
||||
_ = gzipCmd.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -300,11 +303,24 @@ func (r *Remote) Recover(info RecoverInfo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
recoverCmd := fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c '%s -h %s -P %d -u%s -p%s %s --default-character-set=%s %s'",
|
||||
image, r.Type, r.Address, r.Port, r.User, r.Password, sslSkip(info.Version, r.Type), info.Format, info.Name)
|
||||
|
||||
global.LOG.Debug(strings.ReplaceAll(recoverCmd, r.Password, "******"))
|
||||
cmd := exec.Command("bash", "-c", recoverCmd)
|
||||
recoverArgs := []string{
|
||||
"run", "--rm", "--net=host", "-i", image, r.Type,
|
||||
"-h", r.Address,
|
||||
"-P", fmt.Sprintf("%d", r.Port),
|
||||
"-u" + r.User,
|
||||
"-p" + r.Password,
|
||||
sslSkip(info.Version, r.Type),
|
||||
"--default-character-set=" + info.Format,
|
||||
info.Name,
|
||||
}
|
||||
debugArgs := append([]string{}, recoverArgs...)
|
||||
for i, arg := range debugArgs {
|
||||
if strings.Contains(arg, r.Password) {
|
||||
debugArgs[i] = strings.ReplaceAll(arg, r.Password, "******")
|
||||
}
|
||||
}
|
||||
global.LOG.Debug("docker " + strings.Join(debugArgs, " "))
|
||||
cmd := exec.Command("docker", recoverArgs...)
|
||||
|
||||
if strings.HasSuffix(info.SourceFile, ".gz") {
|
||||
gzipFile, err := os.Open(info.SourceFile)
|
||||
|
||||
@@ -62,7 +62,8 @@ func GetRemoteTime(site string) (time.Time, error) {
|
||||
func UpdateSystemTime(dateTime string) error {
|
||||
system := runtime.GOOS
|
||||
if system == "linux" {
|
||||
if err := cmd.RunDefaultBashCf(`%s date -s "%s"`, cmd.SudoHandleCmd(), dateTime); err != nil {
|
||||
cmdMgr := cmd.NewCommandMgr()
|
||||
if err := cmdMgr.RunWithOptionalSudo("date", "-s", dateTime); err != nil {
|
||||
return fmt.Errorf("update system time failed, %v", err)
|
||||
}
|
||||
return nil
|
||||
@@ -73,7 +74,8 @@ func UpdateSystemTime(dateTime string) error {
|
||||
func UpdateSystemTimeZone(timezone string) error {
|
||||
system := runtime.GOOS
|
||||
if system == "linux" {
|
||||
if err := cmd.RunDefaultBashCf(`%s timedatectl set-timezone "%s"`, cmd.SudoHandleCmd(), timezone); err != nil {
|
||||
cmdMgr := cmd.NewCommandMgr()
|
||||
if err := cmdMgr.RunWithOptionalSudo("timedatectl", "set-timezone", timezone); err != nil {
|
||||
return fmt.Errorf("update system time zone failed, %v", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"errors"
|
||||
@@ -14,8 +13,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
)
|
||||
|
||||
@@ -135,29 +134,15 @@ func (r *Local) Backup(info BackupInfo) error {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err)
|
||||
}
|
||||
}
|
||||
outfile, err := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, constant.DirPerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err)
|
||||
}
|
||||
defer outfile.Close()
|
||||
global.LOG.Infof("start to pg_dump | gzip > %s.gzip", info.TargetDir+"/"+info.FileName)
|
||||
|
||||
cmd := exec.Command("docker", "exec", "-i", r.ContainerName,
|
||||
"sh", "-c",
|
||||
fmt.Sprintf("PGPASSWORD=%s pg_dump -F c -U %s -d %s", r.Password, r.Username, info.Name),
|
||||
)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
gzipCmd := exec.Command("gzip", "-cf")
|
||||
gzipCmd.Stdin, _ = cmd.StdoutPipe()
|
||||
gzipCmd.Stdout = outfile
|
||||
_ = gzipCmd.Start()
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("handle backup database failed, err: %v", stderr.String())
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithOutputFile(path.Join(info.TargetDir, info.FileName)))
|
||||
if _, err := cmdMgr.RunPipe(
|
||||
cmd.PipeCommand{Name: "docker", Args: []string{"exec", "-i", "-e", "PGPASSWORD=" + r.Password, r.ContainerName, "pg_dump", "-F", "c", "-U", r.Username, "-d", info.Name}},
|
||||
cmd.PipeCommand{Name: "gzip", Args: []string{"-cf"}},
|
||||
); err != nil {
|
||||
return fmt.Errorf("handle backup database failed, err: %v", err)
|
||||
}
|
||||
_ = gzipCmd.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -165,8 +150,8 @@ func (r *Local) Recover(info RecoverInfo) error {
|
||||
fi, _ := os.Open(info.SourceFile)
|
||||
defer fi.Close()
|
||||
|
||||
cmd := exec.Command("docker", "exec", "-i", r.ContainerName, "sh", "-c",
|
||||
fmt.Sprintf("PGPASSWORD=%s pg_restore -F c -c --if-exists --no-owner -U %s -d %s", r.Password, r.Username, info.Name),
|
||||
cmd := exec.Command("docker", "exec", "-i", "-e", "PGPASSWORD="+r.Password, r.ContainerName,
|
||||
"pg_restore", "-F", "c", "-c", "--if-exists", "--no-owner", "-U", r.Username, "-d", info.Name,
|
||||
)
|
||||
if strings.HasSuffix(info.SourceFile, ".gz") {
|
||||
gzipFile, err := os.Open(info.SourceFile)
|
||||
|
||||
@@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
@@ -24,6 +25,37 @@ import (
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
)
|
||||
|
||||
const maxPgDumpStderrCapture = 64 * 1024
|
||||
|
||||
var pgDumpMagic = []byte("PGDMP")
|
||||
|
||||
type limitedBuffer struct {
|
||||
buf bytes.Buffer
|
||||
limit int
|
||||
truncated int
|
||||
}
|
||||
|
||||
func (b *limitedBuffer) Write(p []byte) (int, error) {
|
||||
if b.limit > 0 && b.buf.Len() >= b.limit {
|
||||
b.truncated += len(p)
|
||||
return len(p), nil
|
||||
}
|
||||
if b.limit > 0 && b.buf.Len()+len(p) > b.limit {
|
||||
keep := b.limit - b.buf.Len()
|
||||
_, _ = b.buf.Write(p[:keep])
|
||||
b.truncated += len(p) - keep
|
||||
return len(p), nil
|
||||
}
|
||||
return b.buf.Write(p)
|
||||
}
|
||||
|
||||
func (b *limitedBuffer) String() string {
|
||||
if b.truncated == 0 {
|
||||
return b.buf.String()
|
||||
}
|
||||
return fmt.Sprintf("%s\n... truncated %d bytes ...", b.buf.String(), b.truncated)
|
||||
}
|
||||
|
||||
type Remote struct {
|
||||
Client *sql.DB
|
||||
From string
|
||||
@@ -160,21 +192,51 @@ func (r *Remote) Backup(info BackupInfo) error {
|
||||
}
|
||||
}
|
||||
fileNameItem := info.TargetDir + "/" + strings.TrimSuffix(info.FileName, ".gz")
|
||||
backupCommand := exec.Command("bash", "-c",
|
||||
fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c 'PGPASSWORD='\\''%s'\\'' pg_dump -h %s -p %d --no-owner -Fc -U %s %s' > %s",
|
||||
imageTag, r.Password, r.Address, r.Port, r.User, info.Name, fileNameItem))
|
||||
_ = backupCommand.Run()
|
||||
b := make([]byte, 5)
|
||||
n := []byte{80, 71, 68, 77, 80}
|
||||
backupFile, err := os.OpenFile(fileNameItem, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
backupFileClosed := false
|
||||
defer func() {
|
||||
if !backupFileClosed {
|
||||
_ = backupFile.Close()
|
||||
}
|
||||
}()
|
||||
backupCommand := exec.Command(
|
||||
"docker",
|
||||
"run", "--rm", "--net=host", "-i",
|
||||
"-e", "PGPASSWORD="+r.Password,
|
||||
imageTag,
|
||||
"pg_dump",
|
||||
"-h", r.Address,
|
||||
"-p", fmt.Sprintf("%d", r.Port),
|
||||
"--no-owner",
|
||||
"-Fc",
|
||||
"-U", r.User,
|
||||
info.Name,
|
||||
)
|
||||
backupCommand.Stdout = backupFile
|
||||
stderr := &limitedBuffer{limit: maxPgDumpStderrCapture}
|
||||
backupCommand.Stderr = stderr
|
||||
if err := backupCommand.Run(); err != nil {
|
||||
return fmt.Errorf("backup failed, stderr: %s, err: %v", strings.TrimSpace(stderr.String()), err)
|
||||
}
|
||||
if err := backupFile.Close(); err != nil {
|
||||
return fmt.Errorf("close backup file failed, err: %v", err)
|
||||
}
|
||||
backupFileClosed = true
|
||||
|
||||
b := make([]byte, len(pgDumpMagic))
|
||||
handle, err := os.OpenFile(fileNameItem, os.O_RDONLY, os.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("backup file not found,err:%v", err)
|
||||
}
|
||||
defer handle.Close()
|
||||
_, _ = handle.Read(b)
|
||||
if string(b) != string(n) {
|
||||
errBytes, _ := os.ReadFile(fileNameItem)
|
||||
return fmt.Errorf("backup failed, err: %s", string(errBytes))
|
||||
if _, err := io.ReadFull(handle, b); err != nil {
|
||||
return fmt.Errorf("read backup header failed, stderr: %s, err: %v", strings.TrimSpace(stderr.String()), err)
|
||||
}
|
||||
if !bytes.Equal(b, pgDumpMagic) {
|
||||
return fmt.Errorf("backup failed, invalid pg dump header: %q, stderr: %s", string(b), strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
gzipCmd := exec.Command("gzip", fileNameItem)
|
||||
@@ -207,9 +269,32 @@ func (r *Remote) Recover(info RecoverInfo) error {
|
||||
_, _ = gzipCmd.CombinedOutput()
|
||||
}()
|
||||
}
|
||||
recoverCommand := exec.Command("bash", "-c",
|
||||
fmt.Sprintf("docker run --rm --net=host -i %s /bin/bash -c 'PGPASSWORD='\\''%s'\\'' pg_restore -h %s -p %d --verbose --clean --no-privileges --no-owner -Fc -c --if-exists --no-owner -U %s -d %s --role=%s' < %s",
|
||||
imageTag, r.Password, r.Address, r.Port, r.User, info.Name, info.Username, fileName))
|
||||
restoreFile, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer restoreFile.Close()
|
||||
recoverCommand := exec.Command(
|
||||
"docker",
|
||||
"run", "--rm", "--net=host", "-i",
|
||||
"-e", "PGPASSWORD="+r.Password,
|
||||
imageTag,
|
||||
"pg_restore",
|
||||
"-h", r.Address,
|
||||
"-p", fmt.Sprintf("%d", r.Port),
|
||||
"--verbose",
|
||||
"--clean",
|
||||
"--no-privileges",
|
||||
"--no-owner",
|
||||
"-Fc",
|
||||
"-c",
|
||||
"--if-exists",
|
||||
"--no-owner",
|
||||
"-U", r.User,
|
||||
"-d", info.Name,
|
||||
"--role="+info.Username,
|
||||
)
|
||||
recoverCommand.Stdin = restoreFile
|
||||
pipe, _ := recoverCommand.StdoutPipe()
|
||||
stderrPipe, _ := recoverCommand.StderrPipe()
|
||||
defer pipe.Close()
|
||||
@@ -230,6 +315,11 @@ func (r *Remote) Recover(info RecoverInfo) error {
|
||||
}
|
||||
global.LOG.Infof("[PostgreSQL] DB:[%s] Restoring: %s", info.Name, readString)
|
||||
}
|
||||
if err := recoverCommand.Wait(); err != nil {
|
||||
all, _ := io.ReadAll(stderrPipe)
|
||||
global.LOG.Errorf("[PostgreSQL] DB:[%s] Recover Error: %s", info.Name, string(all))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (f *Fail2ban) Status() (bool, bool, bool) {
|
||||
}
|
||||
|
||||
func (f *Fail2ban) Version() string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("fail2ban-client version")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)).RunWithStdout("fail2ban-client", "version")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load the fail2ban version failed, %v", err)
|
||||
return "-"
|
||||
@@ -63,7 +63,7 @@ func (f *Fail2ban) Operate(operate string) error {
|
||||
}
|
||||
return nil
|
||||
case "reload":
|
||||
if err := cmd.RunDefaultBashC("fail2ban-client reload"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("fail2ban-client", "reload"); err != nil {
|
||||
return fmt.Errorf("fail2ban-client reload, %v", err)
|
||||
}
|
||||
return nil
|
||||
@@ -91,27 +91,30 @@ func (f *Fail2ban) ReBanIPs(ips []string) error {
|
||||
|
||||
func (f *Fail2ban) ListBanned() ([]string, error) {
|
||||
var lists []string
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("fail2ban-client status sshd | grep 'Banned IP list:'")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)).RunWithStdout("fail2ban-client", "status", "sshd")
|
||||
if err != nil {
|
||||
return lists, err
|
||||
}
|
||||
itemList := strings.Split(strings.Trim(stdout, "\n"), "Banned IP list:")
|
||||
if len(itemList) != 2 {
|
||||
return lists, nil
|
||||
}
|
||||
|
||||
ips := strings.Fields(itemList[1])
|
||||
for _, item := range ips {
|
||||
if len(item) != 0 {
|
||||
lists = append(lists, item)
|
||||
for _, line := range strings.Split(strings.Trim(stdout, "\n"), "\n") {
|
||||
itemList := strings.Split(line, "Banned IP list:")
|
||||
if len(itemList) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
ips := strings.Fields(itemList[1])
|
||||
for _, item := range ips {
|
||||
if len(item) != 0 {
|
||||
lists = append(lists, item)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
return lists, nil
|
||||
}
|
||||
|
||||
func (f *Fail2ban) ListIgnore() ([]string, error) {
|
||||
var lists []string
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("fail2ban-client get sshd ignoreip")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)).RunWithStdout("fail2ban-client", "get", "sshd", "ignoreip")
|
||||
if err != nil {
|
||||
return lists, err
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func NewFtpClient() (*Ftp, error) {
|
||||
|
||||
groupItem, err := user.LookupGroupId("1000")
|
||||
if err == nil {
|
||||
if err := cmd.RunDefaultBashCf("useradd -u 1000 -g %s %s", groupItem.Name, "1panel"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("useradd", "-u", "1000", "-g", groupItem.Name, "1panel"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Ftp{DefaultUser: "1panel", DefaultGroup: groupItem.Name}, nil
|
||||
@@ -71,10 +71,10 @@ func NewFtpClient() (*Ftp, error) {
|
||||
if err.Error() != user.UnknownGroupIdError("1000").Error() {
|
||||
return nil, err
|
||||
}
|
||||
if err := cmd.RunDefaultBashC("groupadd -g 1000 1panel"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("groupadd", "-g", "1000", "1panel"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cmd.RunDefaultBashC("useradd -u 1000 -g 1panel 1panel"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("useradd", "-u", "1000", "-g", "1panel", "1panel"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Ftp{DefaultUser: "1panel", DefaultGroup: "1panel"}, nil
|
||||
@@ -118,7 +118,7 @@ func (f *Ftp) UserAdd(username, passwd, path string) error {
|
||||
return err
|
||||
}
|
||||
_ = f.Reload()
|
||||
if err := cmd.RunDefaultBashCf("chown -R %s:%s %s", f.DefaultUser, f.DefaultGroup, path); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("chown", "-R", f.DefaultUser+":"+f.DefaultGroup, path); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -128,7 +128,7 @@ func (f *Ftp) UserDel(username string) error {
|
||||
if cmd.CheckIllegal(username) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("pure-pw userdel %s", username); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("pure-pw", "userdel", username); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = f.Reload()
|
||||
@@ -189,10 +189,10 @@ func (f *Ftp) SetPath(username, path string) error {
|
||||
if cmd.CheckIllegal(username, path) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("pure-pw usermod %s -d %s", username, path); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("pure-pw", "usermod", username, "-d", path); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("chown -R %s:%s %s", f.DefaultUser, f.DefaultGroup, path); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("chown", "-R", f.DefaultUser+":"+f.DefaultGroup, path); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -202,18 +202,18 @@ func (f *Ftp) SetStatus(username, status string) error {
|
||||
if cmd.CheckIllegal(username, status) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
statusItem := "''"
|
||||
statusItem := ""
|
||||
if status == constant.StatusDisable {
|
||||
statusItem = "1"
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("pure-pw usermod %s -r %s", username, statusItem); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("pure-pw", "usermod", username, "-r", statusItem); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Ftp) LoadList() ([]FtpList, error) {
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("pure-pw list")
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("pure-pw", "list")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -224,14 +224,20 @@ func (f *Ftp) LoadList() ([]FtpList, error) {
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
std2, err := cmd.RunDefaultWithStdoutBashCf("pure-pw show %s | grep 'Allowed client IPs :'", parts[0])
|
||||
std2, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("pure-pw", "show", parts[0])
|
||||
if err != nil {
|
||||
global.LOG.Errorf("handle pure-pw show %s failed, %v", parts[0], err)
|
||||
continue
|
||||
}
|
||||
status := constant.StatusDisable
|
||||
itemStd := strings.ReplaceAll(std2, "\n", "")
|
||||
if len(strings.TrimSpace(strings.ReplaceAll(itemStd, "Allowed client IPs :", ""))) == 0 {
|
||||
allowedLine := ""
|
||||
for _, line := range strings.Split(std2, "\n") {
|
||||
if strings.Contains(line, "Allowed client IPs :") {
|
||||
allowedLine = line
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(strings.TrimSpace(strings.ReplaceAll(allowedLine, "Allowed client IPs :", ""))) == 0 {
|
||||
status = constant.StatusEnable
|
||||
}
|
||||
lists = append(lists, FtpList{User: parts[0], Path: strings.ReplaceAll(parts[1], "/./", ""), Status: status})
|
||||
@@ -240,7 +246,7 @@ func (f *Ftp) LoadList() ([]FtpList, error) {
|
||||
}
|
||||
|
||||
func (f *Ftp) Reload() error {
|
||||
if err := cmd.RunDefaultBashC("pure-pw mkdb"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("pure-pw", "mkdb"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -250,19 +256,28 @@ func (f *Ftp) LoadLogs(user, operation string) ([]FtpLog, error) {
|
||||
var logs []FtpLog
|
||||
logItem := ""
|
||||
if _, err := os.Stat("/etc/pure-ftpd/conf"); err != nil && os.IsNotExist(err) {
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("cat /etc/pure-ftpd/pure-ftpd.conf | grep AltLog | grep clf:")
|
||||
logItem = "/var/log/pureftpd.log"
|
||||
if err == nil && !strings.HasPrefix(std, "#") {
|
||||
logItem = std
|
||||
data, readErr := os.ReadFile("/etc/pure-ftpd/pure-ftpd.conf")
|
||||
if readErr == nil {
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "#") || !strings.Contains(line, "AltLog") || !strings.Contains(line, "clf:") {
|
||||
continue
|
||||
}
|
||||
logItem = line
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
return logs, err
|
||||
}
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("cat /etc/pure-ftpd/conf/AltLog")
|
||||
logItem = "/var/log/pure-ftpd/transfer.log"
|
||||
if err != nil && !strings.HasPrefix(std, "#") {
|
||||
logItem = std
|
||||
data, readErr := os.ReadFile("/etc/pure-ftpd/conf/AltLog")
|
||||
if readErr == nil {
|
||||
std := string(data)
|
||||
if !strings.HasPrefix(strings.TrimSpace(std), "#") {
|
||||
logItem = std
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +313,7 @@ func (f *Ftp) LoadLogs(user, operation string) ([]FtpLog, error) {
|
||||
}
|
||||
|
||||
func handleGunzip(path string) error {
|
||||
if err := cmd.RunDefaultBashCf("gunzip %s", path); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("gunzip", path); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/buserr"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
geo2 "github.com/1Panel-dev/1Panel/core/utils/geo"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/req_helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
@@ -109,5 +115,21 @@ func (u *LogService) CleanLogs(logtype string) error {
|
||||
}
|
||||
|
||||
func writeLogs(version string) {
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("curl -sfL %s | sh -s 1p upgrade %s", logs, version)
|
||||
_ = runRemoteShellScript(logs, "1p", "upgrade", version)
|
||||
}
|
||||
|
||||
func runRemoteShellScript(url string, args ...string) error {
|
||||
statusCode, script, err := req_helper.HandleRequestWithProxy(url, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if statusCode < http.StatusOK || statusCode >= http.StatusMultipleChoices {
|
||||
return fmt.Errorf("download script failed, status code: %d", statusCode)
|
||||
}
|
||||
_, err = cmd.NewCommandMgr().RunPipe(cmd.PipeCommand{
|
||||
Name: "sh",
|
||||
Args: append([]string{"-s"}, args...),
|
||||
Stdin: bytes.NewReader(script),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/req_helper"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/xpack"
|
||||
@@ -173,7 +174,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
fileName := fmt.Sprintf("1panel-%s-%s-%s.tar.gz", req.Version, "linux", itemArch)
|
||||
_ = settingRepo.Update("SystemStatus", "Upgrading")
|
||||
go func() {
|
||||
oldLang := common.LoadParams("LANGUAGE")
|
||||
oldLang := ctl_conf.Load("LANGUAGE")
|
||||
if err := files.DownloadFileWithProxyStream(downloadPath+"/"+fileName, downloadDir+"/"+fileName); err != nil {
|
||||
global.LOG.Errorf("download service file failed, err: %v", err)
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
@@ -219,12 +220,12 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
u.handleRollback(originalDir, 2, svcInfo)
|
||||
return
|
||||
}
|
||||
if _, err := cmd.RunDefaultWithStdoutBashCf("sed -i -e 's#BASE_DIR=.*#BASE_DIR=%s#g' /usr/local/bin/1pctl", global.CONF.Base.InstallDir); err != nil {
|
||||
if err := ctl_conf.UpdateInFile("/usr/local/bin/1pctl", "BASE_DIR", global.CONF.Base.InstallDir); err != nil {
|
||||
global.LOG.Errorf("upgrade basedir in 1pctl failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 2, svcInfo)
|
||||
return
|
||||
}
|
||||
if _, err := cmd.RunDefaultWithStdoutBashCf("sed -i -e 's#LANGUAGE=.*#LANGUAGE=%s#g' /usr/local/bin/1pctl", oldLang); err != nil {
|
||||
if err := ctl_conf.UpdateInFile("/usr/local/bin/1pctl", "LANGUAGE", oldLang); err != nil {
|
||||
global.LOG.Errorf("upgrade basedir in 1pctl failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 2, svcInfo)
|
||||
return
|
||||
@@ -546,7 +547,7 @@ func (u *UpgradeService) loadReleaseNotes(path string) (string, error) {
|
||||
}
|
||||
|
||||
func loadArch() (string, error) {
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("uname -a")
|
||||
std, err := cmd.NewCommandMgr().RunWithStdout("uname", "-a")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("std: %s, err: %s", std, err.Error())
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
cmdUtils "github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/files"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -29,11 +30,10 @@ var restoreCmd = &cobra.Command{
|
||||
fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl restore"}))
|
||||
return nil
|
||||
}
|
||||
stdout, err := cmdUtils.RunDefaultWithStdoutBashC("grep '^BASE_DIR=' /usr/local/bin/1pctl | cut -d'=' -f2")
|
||||
baseDir, err := ctl_conf.LoadFromFile("/usr/local/bin/1pctl", "BASE_DIR")
|
||||
if err != nil {
|
||||
return fmt.Errorf("handle load `BASE_DIR` failed, err: %v", err)
|
||||
}
|
||||
baseDir := strings.ReplaceAll(stdout, "\n", "")
|
||||
upgradeDir := path.Join(baseDir, "1panel", "tmp", "upgrade")
|
||||
|
||||
tmpPath, err := loadRestorePath(upgradeDir)
|
||||
@@ -59,17 +59,17 @@ var restoreCmd = &cobra.Command{
|
||||
if err := files.CopyItem(false, true, path.Join(tmpPath, "GeoIP.mmdb"), path.Join(baseDir, "1panel/geo")); err != nil {
|
||||
return err
|
||||
}
|
||||
sudo := cmdUtils.SudoHandleCmd()
|
||||
_, _ = cmdUtils.RunDefaultWithStdoutBashCf("%s chmod 755 /usr/local/bin/1panel-agent /usr/local/bin/1panel-core", sudo)
|
||||
_, _ = cmdUtils.NewCommandMgr().RunWithStdout("chmod", "755", "/usr/local/bin/1panel-agent", "/usr/local/bin/1panel-core")
|
||||
|
||||
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep2"))
|
||||
if err := files.CopyItem(false, true, path.Join(tmpPath, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = cmdUtils.RunDefaultWithStdoutBashCf("%s chmod 755 /usr/local/bin/1pctl", sudo)
|
||||
_, _ = cmdUtils.RunDefaultWithStdoutBashCf("cp -r %s /usr/local/bin", path.Join(tmpPath, "lang"))
|
||||
_, _ = cmdUtils.NewCommandMgr().RunWithStdout("chmod", "755", "/usr/local/bin/1pctl")
|
||||
_, _ = cmdUtils.NewCommandMgr().RunWithStdout("cp", "-r", "--", path.Join(tmpPath, "lang"), "/usr/local/bin")
|
||||
geoPath := path.Join(global.CONF.Base.InstallDir, "1panel/geo")
|
||||
_, _ = cmdUtils.RunDefaultWithStdoutBashCf("mkdir %s && cp %s %s/", geoPath, path.Join(tmpPath, "GeoIP.mmdb"), geoPath)
|
||||
_ = os.MkdirAll(geoPath, os.ModePerm)
|
||||
_, _ = cmdUtils.NewCommandMgr().RunWithStdout("cp", "--", path.Join(tmpPath, "GeoIP.mmdb"), geoPath+"/")
|
||||
|
||||
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep3"))
|
||||
svcBasePath, _ := controller.GetServicePath("")
|
||||
@@ -137,11 +137,10 @@ func loadRestorePath(upgradeDir string) (string, error) {
|
||||
}
|
||||
|
||||
func loadRollbackVersion(upgradeDir string) string {
|
||||
stdout, err := cmdUtils.RunDefaultWithStdoutBashCf("grep '^ORIGINAL_VERSION=' %s/1pctl | cut -d'=' -f2", upgradeDir)
|
||||
info, err := ctl_conf.LoadFromFile(path.Join(upgradeDir, "1pctl"), "ORIGINAL_VERSION")
|
||||
if err != nil {
|
||||
return "-"
|
||||
}
|
||||
info := strings.ReplaceAll(stdout, "\n", "")
|
||||
if len(info) == 0 || info == `""` {
|
||||
return "-"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/server"
|
||||
cmdUtils "github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/spf13/cobra"
|
||||
"gorm.io/gorm"
|
||||
@@ -38,11 +38,10 @@ type setting struct {
|
||||
}
|
||||
|
||||
func loadDBConn(dbName string) (*gorm.DB, error) {
|
||||
stdout, err := cmdUtils.RunDefaultWithStdoutBashC("grep '^BASE_DIR=' /usr/local/bin/1pctl | cut -d'=' -f2")
|
||||
baseDir, err := ctl_conf.LoadFromFile("/usr/local/bin/1pctl", "BASE_DIR")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("handle load `BASE_DIR` failed, err: %v", err)
|
||||
}
|
||||
baseDir := strings.ReplaceAll(stdout, "\n", "")
|
||||
if len(baseDir) == 0 {
|
||||
return nil, fmt.Errorf("error `BASE_DIR` find in /usr/local/bin/1pctl \n")
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ func port() {
|
||||
fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful"))
|
||||
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortResult", map[string]interface{}{"name": newPortStr}))
|
||||
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("1pctl restart core")
|
||||
std, err := cmd.NewCommandMgr().RunWithStdout("1pctl", "restart", "core")
|
||||
if err != nil {
|
||||
fmt.Println(std)
|
||||
}
|
||||
|
||||
+2
-4
@@ -3,12 +3,12 @@ package i18n
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"golang.org/x/text/language"
|
||||
@@ -209,12 +209,10 @@ func getLanguageFromDBInternal() string {
|
||||
return lang
|
||||
}
|
||||
func getLanguageFrom1pctl() string {
|
||||
cmd := exec.Command("bash", "-c", "grep '^LANGUAGE=' /usr/local/bin/1pctl | cut -d'=' -f2")
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
info, err := ctl_conf.LoadFromFile("/usr/local/bin/1pctl", "LANGUAGE")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
info := strings.ReplaceAll(string(stdout), "\n", "")
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic("error `LANGUAGE` find in /usr/local/bin/1pctl")
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func initLang() {
|
||||
downloadLangFromRemote()
|
||||
return
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("cp -r %s %s", path.Join(tmpPath, "lang"), "/usr/local/bin/"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("cp", "-r", "--", path.Join(tmpPath, "lang"), "/usr/local/bin/"); err != nil {
|
||||
global.LOG.Errorf("load lang from package failed, %v", err)
|
||||
return
|
||||
}
|
||||
@@ -72,7 +72,11 @@ func initLang() {
|
||||
downloadGeoFromRemote(geoPath)
|
||||
return
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("mkdir %s && cp %s %s/", path.Dir(geoPath), path.Join(tmpPath, "GeoIP.mmdb"), path.Dir(geoPath)); err != nil {
|
||||
if err := os.MkdirAll(path.Dir(geoPath), os.ModePerm); err != nil {
|
||||
global.LOG.Errorf("mkdir geo ip dir failed, %v", err)
|
||||
return
|
||||
}
|
||||
if err := cmd.NewCommandMgr().Run("cp", "--", path.Join(tmpPath, "GeoIP.mmdb"), path.Dir(geoPath)+"/"); err != nil {
|
||||
global.LOG.Errorf("load geo ip from package failed, %v", err)
|
||||
return
|
||||
}
|
||||
@@ -113,7 +117,7 @@ func downloadLangFromRemote() {
|
||||
global.LOG.Error("download lang.tar.gz failed, no such file")
|
||||
return
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("tar zxvfC %s %s", "/usr/local/bin/lang.tar.gz", "/usr/local/bin/"); err != nil {
|
||||
if err := cmd.NewCommandMgr().Run("tar", "zxvfC", "/usr/local/bin/lang.tar.gz", "/usr/local/bin/"); err != nil {
|
||||
global.LOG.Errorf("decompress lang.tar.gz failed, %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/app/service"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/encrypt"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/xpack"
|
||||
)
|
||||
@@ -37,12 +38,12 @@ func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
||||
}
|
||||
settingMap := make(map[string]string)
|
||||
if tags == "use_existing" {
|
||||
settingMap["ServerPort"] = common.LoadParams("ORIGINAL_PORT")
|
||||
settingMap["ServerPort"] = ctl_conf.Load("ORIGINAL_PORT")
|
||||
global.CONF.Conn.Port = settingMap["ServerPort"]
|
||||
settingMap["UserName"] = global.CONF.Base.Username
|
||||
settingMap["Password"] = global.CONF.Base.Password
|
||||
settingMap["SecurityEntrance"] = global.CONF.Conn.Entrance
|
||||
settingMap["SystemVersion"] = common.LoadParams("ORIGINAL_VERSION")
|
||||
settingMap["SystemVersion"] = ctl_conf.Load("ORIGINAL_VERSION")
|
||||
global.CONF.Base.Version = settingMap["SystemVersion"]
|
||||
settingMap["Language"] = global.CONF.Base.Language
|
||||
}
|
||||
@@ -81,8 +82,8 @@ func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i '/CHANGE_USER_INFO=%v/d' /usr/local/bin/1pctl", cmd.SudoHandleCmd(), global.CONF.Base.ChangeUserInfo)
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i -e 's#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=**********#g' /usr/local/bin/1pctl", cmd.SudoHandleCmd())
|
||||
_ = ctl_conf.RemoveValueFromFile("/usr/local/bin/1pctl", "CHANGE_USER_INFO", global.CONF.Base.ChangeUserInfo)
|
||||
_ = ctl_conf.UpdateInFile("/usr/local/bin/1pctl", "ORIGINAL_PASSWORD", "**********")
|
||||
}
|
||||
|
||||
func generateKey() {
|
||||
@@ -92,11 +93,10 @@ func generateKey() {
|
||||
}
|
||||
|
||||
func initDockerConf() {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("which docker")
|
||||
dockerPath, err := exec.LookPath("docker")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dockerPath := stdout
|
||||
if strings.Contains(dockerPath, "snap") {
|
||||
constant.DaemonJsonPath = "/var/snap/docker/current/config/daemon.json"
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/init/migration/helper"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/encrypt"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
@@ -55,7 +55,7 @@ var InitSetting = &gormigrate.Migration{
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i -e 's#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=**********#g' /usr/local/bin/1pctl", cmd.SudoHandleCmd())
|
||||
_ = ctl_conf.UpdateInFile("/usr/local/bin/1pctl", "ORIGINAL_PASSWORD", "**********")
|
||||
if err := tx.Create(&model.Setting{Key: "Theme", Value: "light"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+10
-16
@@ -5,12 +5,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/cmd/server/conf"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ctl_conf"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -40,14 +38,14 @@ func Init() {
|
||||
panic(fmt.Errorf("fatal error config file: %s", err))
|
||||
}
|
||||
} else {
|
||||
baseDir = common.LoadParams("BASE_DIR")
|
||||
port = common.LoadParams("ORIGINAL_PORT")
|
||||
version = common.LoadParams("ORIGINAL_VERSION")
|
||||
username = common.LoadParams("ORIGINAL_USERNAME")
|
||||
password = common.LoadParams("ORIGINAL_PASSWORD")
|
||||
entrance = common.LoadParams("ORIGINAL_ENTRANCE")
|
||||
language = common.LoadParams("LANGUAGE")
|
||||
edition = common.LoadParamsWithoutPanic("PANEL_EDITION")
|
||||
baseDir = ctl_conf.Load("BASE_DIR")
|
||||
port = ctl_conf.Load("ORIGINAL_PORT")
|
||||
version = ctl_conf.Load("ORIGINAL_VERSION")
|
||||
username = ctl_conf.Load("ORIGINAL_USERNAME")
|
||||
password = ctl_conf.Load("ORIGINAL_PASSWORD")
|
||||
entrance = ctl_conf.Load("ORIGINAL_ENTRANCE")
|
||||
language = ctl_conf.Load("LANGUAGE")
|
||||
edition = ctl_conf.LoadWithoutPanic("PANEL_EDITION")
|
||||
|
||||
reader := bytes.NewReader(conf.AppYaml)
|
||||
if err := v.ReadConfig(reader); err != nil {
|
||||
@@ -106,9 +104,5 @@ func Init() {
|
||||
}
|
||||
|
||||
func loadChangeInfo() string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("grep '^CHANGE_USER_INFO=' /usr/local/bin/1pctl | cut -d'=' -f2")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.ReplaceAll(stdout, "\n", "")
|
||||
return ctl_conf.LoadWithoutPanic("CHANGE_USER_INFO")
|
||||
}
|
||||
|
||||
+2
-52
@@ -1,11 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func SudoHandleCmd() string {
|
||||
@@ -17,52 +13,6 @@ func SudoHandleCmd() string {
|
||||
}
|
||||
|
||||
func Which(name string) bool {
|
||||
// Prefer Go's built-in PATH lookup so we don't depend on an external
|
||||
// `which` binary, which is not installed by default on minimal
|
||||
// distributions (e.g. Arch Linux, some Alpine images, slim containers).
|
||||
// See 1Panel-dev/1Panel#12605.
|
||||
if _, err := exec.LookPath(name); err == nil {
|
||||
return true
|
||||
}
|
||||
// Fall back to shelling out for environments where PATH inside the
|
||||
// agent process differs from the user's interactive shell PATH (the
|
||||
// previous behaviour, preserved for compatibility).
|
||||
stdout, err := RunDefaultWithStdoutBashCf("which %s", name)
|
||||
if err != nil || (len(strings.ReplaceAll(stdout, "\n", "")) == 0) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func ExecWithStreamOutput(command string, outputCallback func(string)) error {
|
||||
cmd := exec.Command("bash", "-c", command)
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get stdout: %w", err)
|
||||
}
|
||||
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get stderr: %w", err)
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start command: %w", err)
|
||||
}
|
||||
|
||||
go streamReader(stdout, outputCallback)
|
||||
go streamReader(stderr, outputCallback)
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
return fmt.Errorf("command finished with error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func streamReader(reader io.ReadCloser, callback func(string)) {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
callback(scanner.Text())
|
||||
}
|
||||
_, err := exec.LookPath(name)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
+243
-53
@@ -5,10 +5,12 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -17,10 +19,12 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
)
|
||||
|
||||
const maxStreamOutputCapture = 64 * 1024
|
||||
|
||||
type CommandHelper struct {
|
||||
workDir string
|
||||
outputFile string
|
||||
scriptPath string
|
||||
env []string
|
||||
timeout time.Duration
|
||||
taskItem *task.Task
|
||||
logger *log.Logger
|
||||
@@ -29,6 +33,46 @@ type CommandHelper struct {
|
||||
|
||||
type Option func(*CommandHelper)
|
||||
|
||||
type PipeCommand struct {
|
||||
Name string
|
||||
Args []string
|
||||
Env []string
|
||||
Dir string
|
||||
Stdin io.Reader
|
||||
}
|
||||
|
||||
type lockedBuffer struct {
|
||||
mu sync.Mutex
|
||||
buf bytes.Buffer
|
||||
limit int
|
||||
truncated int
|
||||
}
|
||||
|
||||
func (b *lockedBuffer) Write(p []byte) (int, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.limit > 0 && b.buf.Len() >= b.limit {
|
||||
b.truncated += len(p)
|
||||
return len(p), nil
|
||||
}
|
||||
if b.limit > 0 && b.buf.Len()+len(p) > b.limit {
|
||||
keep := b.limit - b.buf.Len()
|
||||
_, _ = b.buf.Write(p[:keep])
|
||||
b.truncated += len(p) - keep
|
||||
return len(p), nil
|
||||
}
|
||||
return b.buf.Write(p)
|
||||
}
|
||||
|
||||
func (b *lockedBuffer) String() string {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.truncated == 0 {
|
||||
return b.buf.String()
|
||||
}
|
||||
return fmt.Sprintf("%s\n... truncated %d bytes ...", b.buf.String(), b.truncated)
|
||||
}
|
||||
|
||||
func NewCommandMgr(opts ...Option) *CommandHelper {
|
||||
s := &CommandHelper{}
|
||||
for _, opt := range opts {
|
||||
@@ -37,49 +81,160 @@ func NewCommandMgr(opts ...Option) *CommandHelper {
|
||||
return s
|
||||
}
|
||||
|
||||
func RunDefaultBashC(command string) error {
|
||||
mgr := NewCommandMgr()
|
||||
return mgr.RunBashC(command)
|
||||
}
|
||||
func RunDefaultBashCf(command string, arg ...interface{}) error {
|
||||
mgr := NewCommandMgr()
|
||||
return mgr.RunBashCf(command, arg...)
|
||||
}
|
||||
func RunDefaultWithStdoutBashC(command string) (string, error) {
|
||||
mgr := NewCommandMgr(WithTimeout(20 * time.Second))
|
||||
return mgr.RunWithStdoutBashC(command)
|
||||
}
|
||||
func RunDefaultWithStdoutBashCf(command string, arg ...interface{}) (string, error) {
|
||||
mgr := NewCommandMgr(WithTimeout(20 * time.Second))
|
||||
return mgr.RunWithStdoutBashCf(command, arg...)
|
||||
}
|
||||
|
||||
func (c *CommandHelper) Run(name string, arg ...string) error {
|
||||
_, err := c.run(name, arg...)
|
||||
return err
|
||||
}
|
||||
func (c *CommandHelper) RunBashCWithArgs(arg ...string) error {
|
||||
arg = append([]string{"-c"}, arg...)
|
||||
_, err := c.run("bash", arg...)
|
||||
return err
|
||||
}
|
||||
func (c *CommandHelper) RunBashC(command string) error {
|
||||
_, err := c.run("bash", "-c", command)
|
||||
return err
|
||||
}
|
||||
func (c *CommandHelper) RunBashCf(command string, arg ...interface{}) error {
|
||||
_, err := c.run("bash", "-c", fmt.Sprintf(command, arg...))
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *CommandHelper) RunWithStdout(name string, arg ...string) (string, error) {
|
||||
return c.run(name, arg...)
|
||||
}
|
||||
func (c *CommandHelper) RunWithStdoutBashC(command string) (string, error) {
|
||||
return c.run("bash", "-c", command)
|
||||
|
||||
func (c *CommandHelper) RunPipe(commands ...PipeCommand) (string, error) {
|
||||
if len(commands) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ctx, cancel := c.pipeContext()
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
cmds := c.buildPipeCommands(ctx, commands)
|
||||
customWriter := &CustomWriter{taskItem: c.taskItem}
|
||||
var outputFile *os.File
|
||||
limitOutputCapture := c.taskItem != nil || c.logger != nil || len(c.outputFile) != 0
|
||||
stdout, stderr := &lockedBuffer{}, &lockedBuffer{}
|
||||
if limitOutputCapture {
|
||||
stdout.limit = maxStreamOutputCapture
|
||||
stderr.limit = maxStreamOutputCapture
|
||||
}
|
||||
if commands[0].Stdin != nil {
|
||||
cmds[0].Stdin = commands[0].Stdin
|
||||
}
|
||||
var pipeStderr io.Writer = stderr
|
||||
var lastStdout io.Writer = stdout
|
||||
var lastStderr io.Writer = stderr
|
||||
var streamWriter io.Writer
|
||||
var streamClosers []io.Closer
|
||||
if c.taskItem != nil {
|
||||
streamWriter = customWriter
|
||||
} else if c.logger != nil {
|
||||
streamWriter = c.logger.Writer()
|
||||
if closer, ok := streamWriter.(io.Closer); ok {
|
||||
streamClosers = append(streamClosers, closer)
|
||||
}
|
||||
} else if len(c.outputFile) != 0 {
|
||||
file, err := os.OpenFile(c.outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, constant.FilePerm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
outputFile = file
|
||||
lastStdout = outputFile
|
||||
}
|
||||
if streamWriter != nil {
|
||||
pipeStderr = io.MultiWriter(stderr, streamWriter)
|
||||
lastStdout = io.MultiWriter(stdout, streamWriter)
|
||||
lastStderr = io.MultiWriter(stderr, streamWriter)
|
||||
}
|
||||
defer func() {
|
||||
if c.taskItem != nil {
|
||||
customWriter.Flush()
|
||||
}
|
||||
for _, closer := range streamClosers {
|
||||
_ = closer.Close()
|
||||
}
|
||||
if outputFile != nil {
|
||||
_ = outputFile.Close()
|
||||
}
|
||||
}()
|
||||
if err := connectPipeCommands(cmds, lastStdout, lastStderr, pipeStderr); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := startPipeCommands(cmds); err != nil {
|
||||
return handleErrString(stdout.String(), stderr.String(), c.IgnoreExist1, err)
|
||||
}
|
||||
|
||||
runErr := waitPipeCommands(ctx, cmds)
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return "", buserr.New("ErrCmdTimeout")
|
||||
}
|
||||
if runErr != nil {
|
||||
return handleErrString(stdout.String(), stderr.String(), c.IgnoreExist1, runErr)
|
||||
}
|
||||
return stdout.String(), nil
|
||||
}
|
||||
func (c *CommandHelper) RunWithStdoutBashCf(command string, arg ...interface{}) (string, error) {
|
||||
return c.run("bash", "-c", fmt.Sprintf(command, arg...))
|
||||
|
||||
func (c *CommandHelper) pipeContext() (context.Context, context.CancelFunc) {
|
||||
ctx := context.Background()
|
||||
if c.timeout == 0 {
|
||||
return ctx, nil
|
||||
}
|
||||
return context.WithTimeout(ctx, c.timeout)
|
||||
}
|
||||
|
||||
func (c *CommandHelper) buildPipeCommands(ctx context.Context, commands []PipeCommand) []*exec.Cmd {
|
||||
cmds := make([]*exec.Cmd, 0, len(commands))
|
||||
for _, item := range commands {
|
||||
cmdItem := exec.CommandContext(ctx, item.Name, item.Args...)
|
||||
cmdItem.Env = append(os.Environ(), c.env...)
|
||||
cmdItem.Env = append(cmdItem.Env, item.Env...)
|
||||
cmdItem.Dir = c.workDir
|
||||
if item.Dir != "" {
|
||||
cmdItem.Dir = item.Dir
|
||||
}
|
||||
cmdItem.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
cmds = append(cmds, cmdItem)
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
||||
func connectPipeCommands(cmds []*exec.Cmd, stdout, stderr, pipeStderr io.Writer) error {
|
||||
for i := 0; i < len(cmds)-1; i++ {
|
||||
pipe, err := cmds[i].StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmds[i+1].Stdin = pipe
|
||||
cmds[i].Stderr = pipeStderr
|
||||
}
|
||||
last := cmds[len(cmds)-1]
|
||||
last.Stdout = stdout
|
||||
last.Stderr = stderr
|
||||
return nil
|
||||
}
|
||||
|
||||
func startPipeCommands(cmds []*exec.Cmd) error {
|
||||
for i := len(cmds) - 1; i >= 0; i-- {
|
||||
if err := cmds[i].Start(); err != nil {
|
||||
killStarted(cmds[i+1:])
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitPipeCommands(ctx context.Context, cmds []*exec.Cmd) error {
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
var runErr error
|
||||
for _, item := range cmds {
|
||||
if err := item.Wait(); err != nil && runErr == nil {
|
||||
runErr = err
|
||||
}
|
||||
}
|
||||
done <- runErr
|
||||
}()
|
||||
select {
|
||||
case runErr := <-done:
|
||||
return runErr
|
||||
case <-ctx.Done():
|
||||
killProcessGroups(cmds)
|
||||
return <-done
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
@@ -97,12 +252,21 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
|
||||
customWriter := &CustomWriter{taskItem: c.taskItem}
|
||||
var stdout, stderr bytes.Buffer
|
||||
var loggerClosers []io.Closer
|
||||
if c.taskItem != nil {
|
||||
cmd.Stdout = customWriter
|
||||
cmd.Stderr = customWriter
|
||||
} else if c.logger != nil {
|
||||
cmd.Stdout = c.logger.Writer()
|
||||
cmd.Stderr = c.logger.Writer()
|
||||
stdoutWriter := c.logger.Writer()
|
||||
stderrWriter := c.logger.Writer()
|
||||
if closer, ok := stdoutWriter.(io.Closer); ok {
|
||||
loggerClosers = append(loggerClosers, closer)
|
||||
}
|
||||
if closer, ok := stderrWriter.(io.Closer); ok {
|
||||
loggerClosers = append(loggerClosers, closer)
|
||||
}
|
||||
cmd.Stdout = stdoutWriter
|
||||
cmd.Stderr = stderrWriter
|
||||
} else if len(c.outputFile) != 0 {
|
||||
file, err := os.OpenFile(c.outputFile, os.O_WRONLY|os.O_CREATE, constant.FilePerm)
|
||||
if err != nil {
|
||||
@@ -111,19 +275,21 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
defer file.Close()
|
||||
cmd.Stdout = file
|
||||
cmd.Stderr = file
|
||||
} else if len(c.scriptPath) != 0 {
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
cmd = exec.Command("bash", c.scriptPath)
|
||||
} else {
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
}
|
||||
env := os.Environ()
|
||||
env = append(env, c.env...)
|
||||
cmd.Env = env
|
||||
if len(c.workDir) != 0 {
|
||||
cmd.Dir = c.workDir
|
||||
}
|
||||
defer func() {
|
||||
for _, closer := range loggerClosers {
|
||||
_ = closer.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if c.timeout != 0 {
|
||||
err := cmd.Run()
|
||||
@@ -140,12 +306,32 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
}
|
||||
|
||||
err := cmd.Run()
|
||||
if c.taskItem != nil {
|
||||
customWriter.Flush()
|
||||
}
|
||||
if err != nil {
|
||||
return handleErr(stdout, stderr, c.IgnoreExist1, err)
|
||||
}
|
||||
return stdout.String(), nil
|
||||
}
|
||||
|
||||
func killStarted(cmds []*exec.Cmd) {
|
||||
killProcessGroups(cmds)
|
||||
for _, item := range cmds {
|
||||
if item.Process != nil {
|
||||
_ = item.Wait()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func killProcessGroups(cmds []*exec.Cmd) {
|
||||
for _, item := range cmds {
|
||||
if item.Process != nil {
|
||||
_ = syscall.Kill(-item.Process.Pid, syscall.SIGKILL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithOutputFile(outputFile string) Option {
|
||||
return func(s *CommandHelper) {
|
||||
s.outputFile = outputFile
|
||||
@@ -171,9 +357,9 @@ func WithWorkDir(workDir string) Option {
|
||||
s.workDir = workDir
|
||||
}
|
||||
}
|
||||
func WithScriptPath(scriptPath string) Option {
|
||||
func WithEnv(env ...string) Option {
|
||||
return func(s *CommandHelper) {
|
||||
s.scriptPath = scriptPath
|
||||
s.env = append(s.env, env...)
|
||||
}
|
||||
}
|
||||
func WithIgnoreExist1() Option {
|
||||
@@ -207,6 +393,10 @@ func (cw *CustomWriter) Flush() {
|
||||
}
|
||||
|
||||
func handleErr(stdout, stderr bytes.Buffer, ignoreExist1 bool, err error) (string, error) {
|
||||
return handleErrString(stdout.String(), stderr.String(), ignoreExist1, err)
|
||||
}
|
||||
|
||||
func handleErrString(stdout, stderr string, ignoreExist1 bool, err error) (string, error) {
|
||||
var exitError *exec.ExitError
|
||||
if ignoreExist1 && errors.As(err, &exitError) {
|
||||
if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
|
||||
@@ -215,16 +405,16 @@ func handleErr(stdout, stderr bytes.Buffer, ignoreExist1 bool, err error) (strin
|
||||
}
|
||||
}
|
||||
}
|
||||
errMsg := ""
|
||||
if len(stderr.String()) != 0 {
|
||||
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
|
||||
outItem := stdout
|
||||
errItem := stderr
|
||||
if len(errItem) != 0 && len(outItem) != 0 {
|
||||
return outItem, fmt.Errorf("stdout: %s; stderr: %s, err: %v", outItem, errItem, err)
|
||||
}
|
||||
if len(stdout.String()) != 0 {
|
||||
if len(errMsg) != 0 {
|
||||
errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String())
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("stdout: %s", stdout.String())
|
||||
}
|
||||
if len(errItem) != 0 {
|
||||
return outItem, fmt.Errorf("stderr: %s, err: %v", errItem, err)
|
||||
}
|
||||
return errMsg, err
|
||||
if len(outItem) != 0 {
|
||||
return outItem, fmt.Errorf("stdout: %s, err: %v", outItem, err)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ func UniqueUints(items []uint) []uint {
|
||||
}
|
||||
|
||||
func LoadArch() (string, error) {
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("uname -a")
|
||||
std, err := cmd.NewCommandMgr().RunWithStdout("uname", "-a")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("std: %s, err: %s", std, err.Error())
|
||||
}
|
||||
@@ -245,25 +245,6 @@ func HandleIPList(content string) ([]string, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func LoadParams(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
info := strings.ReplaceAll(stdout, "\n", "")
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param))
|
||||
}
|
||||
return info
|
||||
}
|
||||
func LoadParamsWithoutPanic(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.ReplaceAll(stdout, "\n", "")
|
||||
}
|
||||
|
||||
func GetRealClientIP(c *gin.Context) string {
|
||||
addr := c.Request.RemoteAddr
|
||||
if ip, _, err := net.SplitHostPort(addr); err == nil {
|
||||
|
||||
@@ -13,18 +13,21 @@ func LoadTimeZoneByCmd() string {
|
||||
if _, err := time.LoadLocation(loc); err != nil {
|
||||
loc = "Asia/Shanghai"
|
||||
}
|
||||
std, err := cmd.RunDefaultWithStdoutBashC("timedatectl | grep 'Time zone'")
|
||||
std, err := cmd.NewCommandMgr().RunWithStdout("timedatectl")
|
||||
if err != nil {
|
||||
return loc
|
||||
}
|
||||
fields := strings.Fields(string(std))
|
||||
if len(fields) != 5 {
|
||||
return loc
|
||||
for _, line := range strings.Split(std, "\n") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) != 5 || fields[0] != "Time" || fields[1] != "zone:" {
|
||||
continue
|
||||
}
|
||||
if _, err := time.LoadLocation(fields[2]); err != nil {
|
||||
return loc
|
||||
}
|
||||
return fields[2]
|
||||
}
|
||||
if _, err := time.LoadLocation(fields[2]); err != nil {
|
||||
return loc
|
||||
}
|
||||
return fields[2]
|
||||
return loc
|
||||
}
|
||||
|
||||
func LoadExpiredLocation() *time.Location {
|
||||
|
||||
@@ -21,7 +21,7 @@ func handlerErr(out string, err error) error {
|
||||
|
||||
func run(client *ssh.SSHClient, name string, args ...string) (string, error) {
|
||||
if client == nil {
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(10*time.Second)).RunWithStdoutBashCf("LANGUAGE=en_US:en %s %s", name, strings.Join(args, " "))
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(10*time.Second), cmd.WithEnv("LANGUAGE=en_US:en")).RunWithStdout(name, args...)
|
||||
}
|
||||
return client.Runf("LANGUAGE=en_US:en %s %s", name, strings.Join(args, " "))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/ssh"
|
||||
@@ -22,18 +23,11 @@ func (s *Openrc) Name() string {
|
||||
return "openrc"
|
||||
}
|
||||
func (s *Openrc) IsActive(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if service %s status >/dev/null 2>&1; then echo 'active'; else echo 'inactive'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "active\n", nil
|
||||
_, err := cmd.NewCommandMgr().RunWithStdout("service", serviceName, "status")
|
||||
return err == nil, nil
|
||||
}
|
||||
func (s *Openrc) IsEnable(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if ls /etc/rc*.d/S*%s >/dev/null 2>&1; then echo 'enabled'; else echo 'disabled'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "enabled\n", nil
|
||||
return isSysvServiceEnabled(serviceName)
|
||||
}
|
||||
func (s *Openrc) IsExist(serviceName string) (bool, error) {
|
||||
if _, err := os.Stat(filepath.Join("/etc/init.d", serviceName)); err != nil {
|
||||
@@ -62,3 +56,27 @@ func (s *Openrc) Operate(operate, serviceName string) error {
|
||||
func (s *Openrc) Reload() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isSysvServiceEnabled(serviceName string) (bool, error) {
|
||||
entries, err := os.ReadDir("/etc")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
name := entry.Name()
|
||||
if !entry.IsDir() || !strings.HasPrefix(name, "rc") || !strings.HasSuffix(name, ".d") {
|
||||
continue
|
||||
}
|
||||
items, err := os.ReadDir(filepath.Join("/etc", name))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, item := range items {
|
||||
itemName := item.Name()
|
||||
if strings.HasPrefix(itemName, "S") && strings.HasSuffix(itemName, serviceName) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -22,18 +22,11 @@ func (s *Sysvinit) Name() string {
|
||||
return "sysvinit"
|
||||
}
|
||||
func (s *Sysvinit) IsActive(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if service %s status >/dev/null 2>&1; then echo 'active'; else echo 'inactive'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "active\n", nil
|
||||
_, err := cmd.NewCommandMgr().RunWithStdout("service", serviceName, "status")
|
||||
return err == nil, nil
|
||||
}
|
||||
func (s *Sysvinit) IsEnable(serviceName string) (bool, error) {
|
||||
out, err := cmd.RunDefaultWithStdoutBashCf("if ls /etc/rc*.d/S*%s >/dev/null 2>&1; then echo 'enabled'; else echo 'disabled'; fi", serviceName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return out == "enabled\n", nil
|
||||
return isSysvServiceEnabled(serviceName)
|
||||
}
|
||||
func (s *Sysvinit) IsExist(serviceName string) (bool, error) {
|
||||
if _, err := os.Stat(filepath.Join("/etc/init.d", serviceName)); err != nil {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package ctl_conf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const defaultFile = "/usr/local/bin/1pctl"
|
||||
|
||||
func Load(key string) string {
|
||||
info, err := LoadFromFile(defaultFile, key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic(fmt.Sprintf("error `%s` find in %s", key, defaultFile))
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func LoadWithoutPanic(key string) string {
|
||||
info, err := LoadFromFile(defaultFile, key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func LoadFromFile(filePath, key string) (string, error) {
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
prefix := key + "="
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.HasPrefix(line, prefix) {
|
||||
return strings.TrimSpace(strings.TrimPrefix(line, prefix)), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("error `%s` find in %s", key, filePath)
|
||||
}
|
||||
|
||||
func UpdateInFile(filePath, key, value string) error {
|
||||
return rewriteFile(filePath, func(line string) (string, bool) {
|
||||
if strings.HasPrefix(line, key+"=") {
|
||||
return key + "=" + value, true
|
||||
}
|
||||
return line, true
|
||||
})
|
||||
}
|
||||
|
||||
func RemoveValueFromFile(filePath, key, value string) error {
|
||||
target := key + "=" + value
|
||||
return rewriteFile(filePath, func(line string) (string, bool) {
|
||||
return line, line != target
|
||||
})
|
||||
}
|
||||
|
||||
func rewriteFile(filePath string, rewrite func(string) (string, bool)) error {
|
||||
info, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content := rewriteLines(string(data), rewrite)
|
||||
return os.WriteFile(filePath, []byte(content), info.Mode().Perm())
|
||||
}
|
||||
|
||||
func rewriteLines(data string, rewrite func(string) (string, bool)) string {
|
||||
hasTrailingNewline := strings.HasSuffix(data, "\n")
|
||||
lines := strings.Split(strings.TrimSuffix(data, "\n"), "\n")
|
||||
rewritten := make([]string, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
newLine, keep := rewrite(line)
|
||||
if keep {
|
||||
rewritten = append(rewritten, newLine)
|
||||
}
|
||||
}
|
||||
content := strings.Join(rewritten, "\n")
|
||||
if hasTrailingNewline {
|
||||
content += "\n"
|
||||
}
|
||||
return content
|
||||
}
|
||||
+90
-36
@@ -61,13 +61,15 @@ func CopyItem(isDir, withName bool, src, dst string) error {
|
||||
_ = os.MkdirAll(dst, srcInfo.Mode())
|
||||
}
|
||||
}
|
||||
cmdStr := fmt.Sprintf(`cp -rf %s %s`, src, dst+"/")
|
||||
cmdArgs := []string{"-rf", "--", src, dst + "/"}
|
||||
cmdText := fmt.Sprintf("cp -rf -- %s %s", src, dst+"/")
|
||||
if !isDir {
|
||||
cmdStr = fmt.Sprintf(`cp -f %s %s`, src, dst+"/")
|
||||
cmdArgs = []string{"-f", "--", src, dst + "/"}
|
||||
cmdText = fmt.Sprintf("cp -f -- %s %s", src, dst+"/")
|
||||
}
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(60 * time.Second)).RunWithStdoutBashC(cmdStr)
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(60*time.Second)).RunWithStdout("cp", cmdArgs...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("handle %s failed, stdout: %s, err: %v", cmdStr, stdout, err)
|
||||
return fmt.Errorf("handle %s failed, stdout: %s, err: %v", cmdText, stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -82,10 +84,11 @@ func CopyFileWithRename(src, dst string) error {
|
||||
_ = os.MkdirAll(path.Dir(dst), srcInfo.Mode())
|
||||
}
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("cp -f %s %s.tmp", src, dst); err != nil {
|
||||
cmdMgr := cmd.NewCommandMgr()
|
||||
if err := cmdMgr.Run("cp", "-f", "--", src, dst+".tmp"); err != nil {
|
||||
return fmt.Errorf("handle cp file failed, err: %v", err)
|
||||
}
|
||||
if err = cmd.RunDefaultBashCf("mv %s.tmp %s", dst, dst); err != nil {
|
||||
if err = cmdMgr.Run("mv", "--", dst+".tmp", dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -98,9 +101,33 @@ func HandleTar(sourceDir, targetDir, name, exclusionRules string, secret string)
|
||||
}
|
||||
}
|
||||
|
||||
targetFile := path.Join(targetDir, name)
|
||||
excludeText, excludeArgs := buildTarExcludeArgs(exclusionRules)
|
||||
tarPathText, tarPathArgs := buildTarPathArgs(sourceDir)
|
||||
if len(secret) != 0 {
|
||||
logTarEncryptCommand(targetFile, excludeText, tarPathText, secret)
|
||||
stdout, err := runTarEncrypt(targetFile, excludeArgs, tarPathArgs, secret)
|
||||
if err != nil && len(stdout) != 0 {
|
||||
global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err)
|
||||
return fmt.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
global.LOG.Debug(fmt.Sprintf("tar -zcf %s %s %s", targetFile, excludeText, tarPathText))
|
||||
stdout, err := runTar(targetFile, excludeArgs, tarPathArgs)
|
||||
if err != nil && len(stdout) != 0 {
|
||||
global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err)
|
||||
return fmt.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildTarExcludeArgs(exclusionRules string) (string, []string) {
|
||||
exMap := make(map[string]struct{})
|
||||
excludes := strings.Split(exclusionRules, ",")
|
||||
excludeRules := ""
|
||||
excludeArgs := []string{}
|
||||
for _, exclude := range excludes {
|
||||
if len(exclude) == 0 {
|
||||
continue
|
||||
@@ -109,39 +136,40 @@ func HandleTar(sourceDir, targetDir, name, exclusionRules string, secret string)
|
||||
continue
|
||||
}
|
||||
excludeRules += fmt.Sprintf(" --exclude '%s'", exclude)
|
||||
excludeArgs = append(excludeArgs, "--exclude", exclude)
|
||||
exMap[exclude] = struct{}{}
|
||||
}
|
||||
path := ""
|
||||
return excludeRules, excludeArgs
|
||||
}
|
||||
|
||||
func buildTarPathArgs(sourceDir string) (string, []string) {
|
||||
tarPath := ""
|
||||
tarPathArgs := []string{}
|
||||
if strings.Contains(sourceDir, "/") {
|
||||
itemDir := strings.ReplaceAll(sourceDir[strings.LastIndex(sourceDir, "/"):], "/", "")
|
||||
aheadDir := sourceDir[:strings.LastIndex(sourceDir, "/")]
|
||||
if len(aheadDir) == 0 {
|
||||
aheadDir = "/"
|
||||
}
|
||||
path += fmt.Sprintf("-C %s %s", aheadDir, itemDir)
|
||||
tarPath += fmt.Sprintf("-C %s %s", aheadDir, itemDir)
|
||||
tarPathArgs = append(tarPathArgs, "-C", aheadDir, itemDir)
|
||||
} else {
|
||||
path = sourceDir
|
||||
tarPath = sourceDir
|
||||
tarPathArgs = append(tarPathArgs, sourceDir)
|
||||
}
|
||||
return tarPath, tarPathArgs
|
||||
}
|
||||
|
||||
commands := ""
|
||||
func logTarEncryptCommand(targetFile, excludeRules, tarPath, secret string) {
|
||||
extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out"
|
||||
command := fmt.Sprintf("tar -zcf %s %s %s %s", " -"+excludeRules, tarPath, extraCmd, targetFile)
|
||||
global.LOG.Debug(strings.ReplaceAll(command, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
}
|
||||
|
||||
if len(secret) != 0 {
|
||||
extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out"
|
||||
commands = fmt.Sprintf("tar -zcf %s %s %s %s", " -"+excludeRules, path, extraCmd, targetDir+"/"+name)
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zcf %s %s %s", targetDir+"/"+name, excludeRules, path)
|
||||
global.LOG.Debug(commands)
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour), cmd.WithIgnoreExist1())
|
||||
stdout, err := cmdMgr.RunWithStdoutBashC(commands)
|
||||
if err != nil {
|
||||
if len(stdout) != 0 {
|
||||
global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err)
|
||||
return fmt.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
func runTar(targetFile string, excludeArgs, tarPathArgs []string) (string, error) {
|
||||
tarArgs := append([]string{"-zcf", targetFile}, excludeArgs...)
|
||||
tarArgs = append(tarArgs, tarPathArgs...)
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour), cmd.WithIgnoreExist1()).RunWithStdout("tar", tarArgs...)
|
||||
}
|
||||
|
||||
func HandleUnTar(sourceFile, targetDir string, secret string) error {
|
||||
@@ -150,18 +178,18 @@ func HandleUnTar(sourceFile, targetDir string, secret string) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
commands := ""
|
||||
if len(secret) != 0 {
|
||||
extraCmd := "openssl enc -d -aes-256-cbc -k '" + secret + "' -in " + sourceFile + " | "
|
||||
commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, targetDir+" > /dev/null 2>&1")
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar zxvf '%s' -C '%s'", sourceFile, targetDir)
|
||||
global.LOG.Debug(commands)
|
||||
logTarDecryptCommand(sourceFile, targetDir, secret)
|
||||
stdout, err := runTarDecrypt(sourceFile, targetDir, secret)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err)
|
||||
return errors.New(stdout)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(24 * time.Hour))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashC(commands)
|
||||
global.LOG.Debug(fmt.Sprintf("tar zxvf '%s' -C '%s'", sourceFile, targetDir))
|
||||
stdout, err := runUnTar(sourceFile, targetDir)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err)
|
||||
return errors.New(stdout)
|
||||
@@ -169,6 +197,32 @@ func HandleUnTar(sourceFile, targetDir string, secret string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func logTarDecryptCommand(sourceFile, targetDir, secret string) {
|
||||
extraCmd := "openssl enc -d -aes-256-cbc -k '" + secret + "' -in " + sourceFile + " | "
|
||||
command := fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, targetDir+" > /dev/null 2>&1")
|
||||
global.LOG.Debug(strings.ReplaceAll(command, fmt.Sprintf(" '%s' ", secret), " ****** "))
|
||||
}
|
||||
|
||||
func runUnTar(sourceFile, targetDir string) (string, error) {
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour)).RunWithStdout("tar", "zxf", sourceFile, "-C", targetDir)
|
||||
}
|
||||
|
||||
func runTarEncrypt(targetFile string, excludeArgs, tarPathArgs []string, secret string) (string, error) {
|
||||
tarArgs := append([]string{"-zcf", "-"}, excludeArgs...)
|
||||
tarArgs = append(tarArgs, tarPathArgs...)
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour)).RunPipe(
|
||||
cmd.PipeCommand{Name: "tar", Args: tarArgs},
|
||||
cmd.PipeCommand{Name: "openssl", Args: []string{"enc", "-aes-256-cbc", "-salt", "-pass", "env:BACKUP_SECRET", "-out", targetFile}, Env: []string{"BACKUP_SECRET=" + secret}},
|
||||
)
|
||||
}
|
||||
|
||||
func runTarDecrypt(sourceFile, targetDir, secret string) (string, error) {
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour)).RunPipe(
|
||||
cmd.PipeCommand{Name: "openssl", Args: []string{"enc", "-d", "-aes-256-cbc", "-pass", "env:BACKUP_SECRET", "-in", sourceFile}, Env: []string{"BACKUP_SECRET=" + secret}},
|
||||
cmd.PipeCommand{Name: "tar", Args: []string{"-zxf", "-", "-C", targetDir}},
|
||||
)
|
||||
}
|
||||
|
||||
func DownloadFile(url, dst string) error {
|
||||
resp, err := req_helper.HandleGet(url)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package firewall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
)
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
func UpdatePort(oldPort, newPort string) error {
|
||||
firewalld := cmd.Which("firewalld")
|
||||
if firewalld {
|
||||
status, _ := cmd.RunDefaultWithStdoutBashC("LANGUAGE=en_US:en firewall-cmd --state")
|
||||
status, _ := cmd.NewCommandMgr(cmd.WithEnv("LANGUAGE=en_US:en")).RunWithStdout("firewall-cmd", "--state")
|
||||
isRunning := status == "running\n"
|
||||
if isRunning {
|
||||
return firewallUpdatePort(oldPort, newPort)
|
||||
@@ -20,8 +21,8 @@ func UpdatePort(oldPort, newPort string) error {
|
||||
if !ufw {
|
||||
return nil
|
||||
}
|
||||
status, _ := cmd.RunDefaultWithStdoutBashC("LANGUAGE=en_US:en ufw status | grep Status")
|
||||
isRuning := status == "Status: active\n"
|
||||
status, _ := cmd.NewCommandMgr(cmd.WithEnv("LANGUAGE=en_US:en")).RunWithStdout("ufw", "status")
|
||||
isRuning := strings.Contains(status, "Status: active")
|
||||
if isRuning {
|
||||
return ufwUpdatePort(oldPort, newPort)
|
||||
}
|
||||
@@ -29,22 +30,22 @@ func UpdatePort(oldPort, newPort string) error {
|
||||
}
|
||||
|
||||
func firewallUpdatePort(oldPort, newPort string) error {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("firewall-cmd --zone=public --add-port=%s/tcp --permanent", newPort)
|
||||
stdout, err := cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--add-port="+newPort+"/tcp", "--permanent")
|
||||
if err != nil {
|
||||
return fmt.Errorf("add (port: %s/tcp) failed, err: %s", newPort, stdout)
|
||||
}
|
||||
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("firewall-cmd --zone=public --remove-port=%s/tcp --permanent", oldPort)
|
||||
_, _ = cmd.RunDefaultWithStdoutBashC("firewall-cmd --reload")
|
||||
_, _ = cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--zone=public", "--remove-port="+oldPort+"/tcp", "--permanent")
|
||||
_, _ = cmd.NewCommandMgr().RunWithStdout("firewall-cmd", "--reload")
|
||||
return nil
|
||||
}
|
||||
|
||||
func ufwUpdatePort(oldPort, newPort string) error {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("ufw allow %s", newPort)
|
||||
stdout, err := cmd.NewCommandMgr().RunWithStdout("ufw", "allow", newPort)
|
||||
if err != nil {
|
||||
return fmt.Errorf("add (port: %s/tcp) failed, err: %s", newPort, stdout)
|
||||
}
|
||||
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("ufw delete allow %s", oldPort)
|
||||
_, _ = cmd.NewCommandMgr().RunWithStdout("ufw", "delete", "allow", oldPort)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user