diff --git a/internal/deployer/ssh.go b/internal/deployer/ssh.go index 7aa04cac..b028fd61 100644 --- a/internal/deployer/ssh.go +++ b/internal/deployer/ssh.go @@ -19,14 +19,15 @@ type ssh struct { } type sshAccess struct { - Host string `json:"host"` - Username string `json:"username"` - Password string `json:"password"` - Key string `json:"key"` - Port string `json:"port"` - Command string `json:"command"` - CertPath string `json:"certPath"` - KeyPath string `json:"keyPath"` + Host string `json:"host"` + Username string `json:"username"` + Password string `json:"password"` + Key string `json:"key"` + Port string `json:"port"` + PreCommand string `json:"preCommand"` + Command string `json:"command"` + CertPath string `json:"certPath"` + KeyPath string `json:"keyPath"` } func NewSSH(option *DeployerOption) (Deployer, error) { @@ -56,6 +57,7 @@ func (s *ssh) Deploy(ctx context.Context) error { access.CertPath = strings.ReplaceAll(access.CertPath, key, v) access.KeyPath = strings.ReplaceAll(access.KeyPath, key, v) access.Command = strings.ReplaceAll(access.Command, key, v) + access.PreCommand = strings.ReplaceAll(access.PreCommand, key, v) } // 连接 @@ -67,14 +69,13 @@ func (s *ssh) Deploy(ctx context.Context) error { s.infos = append(s.infos, toStr("ssh连接成功", nil)) - // 上传 - session, err := client.NewSession() - if err != nil { - return fmt.Errorf("failed to create session: %w", err) + // 执行前置命令 + if access.PreCommand != "" { + err, stdout, stderr := s.sshExecCommand(client, access.Command) + if err != nil { + return fmt.Errorf("failed to run pre-command: %w, stdout: %s, stderr: %s", err, stdout, stderr) + } } - defer session.Close() - - s.infos = append(s.infos, toStr("ssh创建session成功", nil)) // 上传证书 if err := s.upload(client, s.option.Certificate.Certificate, access.CertPath); err != nil { @@ -91,18 +92,28 @@ func (s *ssh) Deploy(ctx context.Context) error { s.infos = append(s.infos, toStr("ssh上传私钥成功", nil)) // 执行命令 + err, stdout, stderr := s.sshExecCommand(client, access.Command) + if err != nil { + return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdout, stderr) + } + + s.infos = append(s.infos, toStr("ssh执行命令成功", stdout)) + + return nil +} + +func (s *ssh) sshExecCommand(client *sshPkg.Client, command string) (error, string, string) { + session, err := client.NewSession() + if err != nil { + return fmt.Errorf("failed to create ssh session: %w", err), "", "" + } + defer session.Close() var stdoutBuf bytes.Buffer session.Stdout = &stdoutBuf var stderrBuf bytes.Buffer session.Stderr = &stderrBuf - - if err := session.Run(access.Command); err != nil { - return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdoutBuf.String(), stderrBuf.String()) - } - - s.infos = append(s.infos, toStr("ssh执行命令成功", []string{stdoutBuf.String()})) - - return nil + err = session.Run(command) + return err, stdoutBuf.String(), stderrBuf.String() } func (s *ssh) upload(client *sshPkg.Client, content, path string) error { diff --git a/ui/package.json b/ui/package.json index d151ae32..ea0b2cb3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" diff --git a/ui/src/components/certimate/AccessSSHForm.tsx b/ui/src/components/certimate/AccessSSHForm.tsx index b7af5b4e..cf055b44 100644 --- a/ui/src/components/certimate/AccessSSHForm.tsx +++ b/ui/src/components/certimate/AccessSSHForm.tsx @@ -79,6 +79,7 @@ const AccessSSHForm = ({ key: z.string().min(0).max(20480), keyFile: z.any().optional(), command: z.string().min(1).max(2048), + preCommand: z.string().min(0).max(2048).optional(), certPath: z.string().min(0).max(2048), keyPath: z.string().min(0).max(2048), }); @@ -90,6 +91,7 @@ const AccessSSHForm = ({ password: "", key: "", keyFile: "", + preCommand: "", command: "sudo service nginx restart", certPath: "/etc/nginx/ssl/certificate.crt", keyPath: "/etc/nginx/ssl/private.key", @@ -112,6 +114,7 @@ const AccessSSHForm = ({ certPath: config.certPath, keyPath: config.keyPath, command: config.command, + preCommand: config.preCommand, }, }); @@ -133,6 +136,7 @@ const AccessSSHForm = ({ password: data.password, key: data.key, command: data.command, + preCommand: data.preCommand, certPath: data.certPath, keyPath: data.keyPath, }, @@ -468,6 +472,21 @@ const AccessSSHForm = ({ )} /> + ( + + 前置 Command + +