diff --git a/backend/app/dto/ssh.go b/backend/app/dto/ssh.go index b8c9544d1..a2a05477e 100644 --- a/backend/app/dto/ssh.go +++ b/backend/app/dto/ssh.go @@ -3,6 +3,7 @@ package dto import "time" type SSHInfo struct { + AutoStart bool `json:"authStart"` Status string `json:"status"` Message string `json:"message"` Port string `json:"port"` diff --git a/backend/app/service/ssh.go b/backend/app/service/ssh.go index b0d71ea80..b4f2d6e2f 100644 --- a/backend/app/service/ssh.go +++ b/backend/app/service/ssh.go @@ -45,6 +45,7 @@ func NewISSHService() ISSHService { func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) { data := dto.SSHInfo{ + AutoStart: true, Status: constant.StatusEnable, Message: "", Port: "22", @@ -67,7 +68,7 @@ func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) { data.Status = constant.StatusEnable } } - + data.AutoStart, _ = systemctl.IsEnable(serviceName) sshConf, err := os.ReadFile(sshPath) if err != nil { data.Message = err.Error() @@ -98,19 +99,19 @@ func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) { } func (u *SSHService) OperateSSH(operation string) error { - if operation == "start" || operation == "stop" || operation == "restart" { - serviceName, err := loadServiceName() - if err != nil { - return err - } - sudo := cmd.SudoHandleCmd() - stdout, err := cmd.Execf("%s systemctl %s %s", sudo, operation, serviceName) - if err != nil { - return fmt.Errorf("%s %s failed, stdout: %s, err: %v", operation, serviceName, stdout, err) - } - return nil + serviceName, err := loadServiceName() + if err != nil { + return err } - return fmt.Errorf("not support such operation: %s", operation) + sudo := cmd.SudoHandleCmd() + if operation == "enable" || operation == "disable" { + serviceName += ".service" + } + stdout, err := cmd.Execf("%s systemctl %s %s", sudo, operation, serviceName) + if err != nil { + return fmt.Errorf("%s %s failed, stdout: %s, err: %v", operation, serviceName, stdout, err) + } + return nil } func (u *SSHService) Update(key, value string) error { diff --git a/backend/utils/systemctl/systemctl.go b/backend/utils/systemctl/systemctl.go index 402fbf7a0..7d370cc0a 100644 --- a/backend/utils/systemctl/systemctl.go +++ b/backend/utils/systemctl/systemctl.go @@ -2,9 +2,10 @@ package systemctl import ( "fmt" - "github.com/pkg/errors" "os/exec" "strings" + + "github.com/pkg/errors" ) func RunSystemCtl(args ...string) (string, error) { @@ -24,6 +25,14 @@ func IsActive(serviceName string) (bool, error) { return out == "active\n", nil } +func IsEnable(serviceName string) (bool, error) { + out, err := RunSystemCtl("is-enabled", serviceName) + if err != nil { + return false, err + } + return out == "enabled\n", nil +} + func IsExist(serviceName string) (bool, error) { out, err := RunSystemCtl("list-unit-files") if err != nil { diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 5faa3d7e4..ceeb7b505 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -14818,6 +14818,9 @@ const docTemplate = `{ "dto.SSHInfo": { "type": "object", "properties": { + "authStart": { + "type": "boolean" + }, "listenAddress": { "type": "string" }, @@ -16277,6 +16280,21 @@ const docTemplate = `{ }, "showHidden": { "type": "boolean" + }, + "sortBy": { + "type": "string", + "enum": [ + "name", + "size", + "modTime" + ] + }, + "sortOrder": { + "type": "string", + "enum": [ + "ascending", + "descending" + ] } } }, diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index f1d02c414..074511a39 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -14811,6 +14811,9 @@ "dto.SSHInfo": { "type": "object", "properties": { + "authStart": { + "type": "boolean" + }, "listenAddress": { "type": "string" }, @@ -16270,6 +16273,21 @@ }, "showHidden": { "type": "boolean" + }, + "sortBy": { + "type": "string", + "enum": [ + "name", + "size", + "modTime" + ] + }, + "sortOrder": { + "type": "string", + "enum": [ + "ascending", + "descending" + ] } } }, diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 7e201f2b9..4d64f43d3 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -1861,6 +1861,8 @@ definitions: type: object dto.SSHInfo: properties: + authStart: + type: boolean listenAddress: type: string message: @@ -2832,6 +2834,17 @@ definitions: type: string showHidden: type: boolean + sortBy: + enum: + - name + - size + - modTime + type: string + sortOrder: + enum: + - ascending + - descending + type: string type: object request.FilePathCheck: properties: diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 12081bf5a..f524c72c5 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -955,6 +955,9 @@ const message = { fileHeper: 'Note: 1. Sorting is not supported after searching 2. Folders are not supported by size sorting', }, ssh: { + autoStart: 'Auto Start', + enable: 'Enable Autostart', + disable: 'Disable Autostart', sshAlert: 'The list data is sorted based on login time, but please note that changing time zones or other operations may cause deviations in the time of login logs.', sshOperate: 'Operation [{0}] on the SSH service is performed. Do you want to continue?', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 65ea1aa90..229b97f83 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -919,6 +919,9 @@ const message = { fileHeper: '注意:1.搜尋之後不支援排序 2.依大小排序不支援資料夾', }, ssh: { + autoStart: '開機自啟', + enable: '設置開機自啟', + disable: '關閉開機自啟', sshAlert: '列表數據根據登錄時間排序,但請註意,切換時區或其他操作可能導致登錄日誌的時間出現偏差。', sshOperate: '對 SSH 服務進行 [{0}] 操作,是否繼續?', sshChange: 'SSH 配置修改', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 1670f1b29..e1c40949d 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -919,6 +919,9 @@ const message = { fileHeper: '注意:1.搜索之后不支持排序 2.按大小排序不支持文件夹', }, ssh: { + autoStart: '开机自启', + enable: '设置开机自启', + disable: '关闭开机自启', sshAlert: '列表数据根据登录时间排序,但请注意,切换时区或其他操作可能导致登录日志的时间出现偏差。', sshOperate: '对 SSH 服务进行 [{0}] 操作,是否继续?', sshChange: 'SSH 配置修改', diff --git a/frontend/src/views/host/ssh/ssh/index.vue b/frontend/src/views/host/ssh/ssh/index.vue index cc6a0b768..c107dcba8 100644 --- a/frontend/src/views/host/ssh/ssh/index.vue +++ b/frontend/src/views/host/ssh/ssh/index.vue @@ -22,23 +22,28 @@ - - + + {{ $t('commons.button.stop') }} - - - {{ $t('container.restart') }} - - - - + {{ $t('commons.button.start') }} {{ $t('container.restart') }} + + + {{ $t('ssh.autoStart') }} + + @@ -170,6 +175,8 @@ const portRef = ref(); const addressRef = ref(); const rootsRef = ref(); +const autoStart = ref('enable'); + const sshConf = ref(); const form = reactive({ status: 'enable', @@ -218,22 +225,28 @@ const onChangeAddress = () => { }; const onOperate = async (operation: string) => { - ElMessageBox.confirm(i18n.global.t('ssh.sshOperate', [i18n.global.t('commons.button.' + operation)]), 'SSH', { + let msg = operation === 'enable' || operation === 'disable' ? 'ssh.' : 'commons.button.'; + ElMessageBox.confirm(i18n.global.t('ssh.sshOperate', [i18n.global.t(msg + operation)]), 'SSH', { confirmButtonText: i18n.global.t('commons.button.confirm'), cancelButtonText: i18n.global.t('commons.button.cancel'), type: 'info', - }).then(async () => { - loading.value = true; - await operateSSH(operation) - .then(() => { - loading.value = false; - MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); - search(); - }) - .catch(() => { - loading.value = false; - }); - }); + }) + .then(async () => { + loading.value = true; + await operateSSH(operation) + .then(() => { + loading.value = false; + MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); + search(); + }) + .catch(() => { + autoStart.value = operation === 'enable' ? 'disable' : 'enable'; + loading.value = false; + }); + }) + .catch(() => { + autoStart.value = operation === 'enable' ? 'disable' : 'enable'; + }); }; const onSave = async (formEl: FormInstance | undefined, key: string, value: string) => {