Browse Source

继续编写sshd远程运维模块的client代码

niujiuru 2 weeks ago
parent
commit
014d32109d
5 changed files with 106 additions and 12 deletions
  1. 1 1
      Makefile
  2. 1 1
      main.go
  3. 97 3
      sshd/client/client.go
  4. 3 3
      sshd/client/coupler.go
  5. 4 4
      sshd/client/invoker.go

+ 1 - 1
Makefile

@@ -133,7 +133,7 @@ yfkj_sshd.out       : libswapi.a libair530z.a ./sshd/server/server.go
 yfkj_ssh_client.out : libswapi.a libair530z.a ./sshd/client/client.go
 	mkdir -p ./build
 	$(GO) mod tidy
-	$(SETGO_ENV) CGO_LDFLAGS="$(LIB6)" $(GO_BUILD) $(GO_FLAGS) -o $@ ./sshd/client/client.go
+	$(SETGO_ENV) CGO_LDFLAGS="$(LIB6)" $(GO_BUILD) $(GO_FLAGS) -o $@ ./sshd/client
 	@cp $@ ./build/$(basename $@)_$(DATE)$(suffix $@)
 
 # 综合应用测试程序

+ 1 - 1
main.go

@@ -86,7 +86,7 @@ func main() {
 	if baseapp.GetArgsParamStr("-install", "") == "boot" {
 		err := enableAutoStartOnBoot()
 		if err != nil {
-			fmt.Printf("设置开机自启动失败: %v", err)
+			fmt.Printf("设置开机自启动失败: %v\n", err)
 		} else {
 			fmt.Println("设置开机自启动成功")
 		}

+ 97 - 3
sshd/client/client.go

@@ -1,9 +1,17 @@
 package main
 
 import (
+	"bufio"
 	"context"
 	"errors"
 	"fmt"
+	"io"
+	"os"
+	"os/signal"
+	"strings"
+	"sync/atomic"
+	"syscall"
+	"time"
 
 	"github.com/google/uuid"
 	"hnyfkj.com.cn/rtu/linux/baseapp"
@@ -36,11 +44,11 @@ func main() {
 	}
 
 	if err := loadAppConfig(); err != nil {
-		fmt.Printf("[%s] 错误: %v!!", MODULE_NAME, err)
+		fmt.Printf("[%s] 错误: %v!!\n", MODULE_NAME, err)
 		return
 	}
 	if CfgServers.MQTTSrv.Address == "" {
-		fmt.Printf("[%s] 错误: %v!!", MODULE_NAME, ErrBrokerAddressEmpty)
+		fmt.Printf("[%s] 错误: %v!!\n", MODULE_NAME, ErrBrokerAddressEmpty)
 		return
 	}
 
@@ -57,7 +65,7 @@ func main() {
 	}
 
 	if err := coupler.init2(); err != nil {
-		fmt.Printf("[%s] 错误: %v!!", MODULE_NAME, err)
+		fmt.Printf("[%s] 错误: %v\n!!", MODULE_NAME, err)
 		return
 	}
 
@@ -73,7 +81,65 @@ func main() {
 // 6, 等待返回结果, 打印输出
 // 7, 循环等待下次, 直到退出
 func term() {
+	var pingState atomic.Bool
+	var executing atomic.Bool
+
+	// -在线-心跳检测
+	heartbeatLoop(&pingState)
+
+	// Ctrl+C中断处理
+	interruptLoop(&executing)
+
+	reader := bufio.NewReader(os.Stdin)
 	for {
+		if !pingState.Load() {
+			fmt.Printf("[%s] 无法连接目标设备!!\n", MODULE_NAME)
+			break
+		}
+
+		fmt.Print("\033[?25h") // 显示光标
+		fmt.Printf("root@%s:%s# ", coupler.imei, coupler.cwd)
+
+		input, err := reader.ReadString('\n')
+		if err != nil {
+			if err == io.EOF {
+				os.Exit(0)
+			}
+			fmt.Println("读取用户输入失败:", err)
+			continue
+		}
+
+		input = strings.TrimSpace(input)
+		if input == "" {
+			continue
+		}
+
+		switch input {
+		case "quit":
+			_, _ = coupler.quit()
+			os.Exit(0)
+		}
+
+		fmt.Print("\033[?25l") // 隐藏光标
+		executing.Store(true)
+		result, err := coupler.exec(input)
+		executing.Store(false)
+
+		if err != nil {
+			fmt.Printf("执行错误: %v\n", err)
+			continue
+		}
+
+		if result.Stdout != "" {
+			fmt.Println(result.Stdout)
+		}
+		if result.Stderr != "" {
+			fmt.Fprintln(os.Stderr, result.Stderr)
+		}
+
+		if result.Cwd != "" {
+			coupler.cwd = result.Cwd
+		}
 	}
 }
 
@@ -86,3 +152,31 @@ func help() {
 
 	fmt.Println(h)
 }
+
+func interruptLoop(executing *atomic.Bool) {
+	sigCh := make(chan os.Signal, 1)
+	signal.Notify(sigCh, syscall.SIGINT)
+	go func() {
+		for range sigCh {
+			if executing.Load() {
+				_, _ = coupler.stop()
+			}
+			fmt.Print("\n^C\n")
+		} // end for
+	}()
+}
+
+func heartbeatLoop(pingState *atomic.Bool) {
+	go func() {
+		ticker := time.NewTicker(1 * time.Second)
+		defer ticker.Stop()
+		for range ticker.C {
+			resp, err := coupler.ping()
+			if err == nil && resp.Error == nil && resp.Result != nil && string(resp.Result) == "pong" {
+				pingState.Store(true)
+			} else {
+				pingState.Store(false)
+			} // end if
+		} // end for
+	}()
+}

+ 3 - 3
sshd/client/coupler.go

@@ -54,7 +54,7 @@ func (c *MQTTCoupler) init2() error {
 
 	opts.OnConnect = func(client mqtt.Client) {
 		if !c.isConnected.Swap(true) {
-			fmt.Printf("[%s] MQTT Broker连接成功", MODULE_NAME)
+			fmt.Printf("[%s] MQTT Broker连接成功\n", MODULE_NAME)
 		}
 		go func() { // 订阅应答主题
 			token := c.client.Subscribe(c.subTopic, MqttQos1, c.onCmdAck)
@@ -71,7 +71,7 @@ func (c *MQTTCoupler) init2() error {
 
 	opts.OnConnectionLost = func(client mqtt.Client, err error) {
 		if c.isConnected.Swap(false) {
-			fmt.Printf("[%s] MQTT Broker连接丢失: %v!", MODULE_NAME, err)
+			fmt.Printf("[%s] MQTT Broker连接丢失: %v!\n", MODULE_NAME, err)
 		}
 	}
 
@@ -103,7 +103,7 @@ func (c *MQTTCoupler) tick() time.Duration {
 	}
 
 	if err := c.connect(); err != nil {
-		fmt.Printf("[%s] MQTT Broker连接失败: %v!!", MODULE_NAME, err)
+		fmt.Printf("[%s] MQTT Broker连接失败: %v!!\n", MODULE_NAME, err)
 	}
 
 	return SlowInterval

+ 4 - 4
sshd/client/invoker.go

@@ -40,7 +40,7 @@ func (c *MQTTCoupler) needTimeoutEnd(method string) bool {
 }
 
 // 心跳检测
-func (c *MQTTCoupler) Ping() (jsonrpc2.Response, error) {
+func (c *MQTTCoupler) ping() (jsonrpc2.Response, error) {
 	params := struct {
 		ClientID string `json:"client_id"`
 	}{
@@ -51,7 +51,7 @@ func (c *MQTTCoupler) Ping() (jsonrpc2.Response, error) {
 }
 
 // 执行命令
-func (c *MQTTCoupler) Exec(
+func (c *MQTTCoupler) exec(
 	cmd string) (shell.ExecuteResult, error) {
 	params := struct {
 		ClientID string `json:"client_id"`
@@ -88,7 +88,7 @@ func (c *MQTTCoupler) Exec(
 }
 
 // 中断执行
-func (c *MQTTCoupler) Stop() (jsonrpc2.Response, error) {
+func (c *MQTTCoupler) stop() (jsonrpc2.Response, error) {
 	params := struct {
 		ClientID string `json:"client_id"`
 	}{
@@ -99,7 +99,7 @@ func (c *MQTTCoupler) Stop() (jsonrpc2.Response, error) {
 }
 
 // 关闭退出
-func (c *MQTTCoupler) Quit() (jsonrpc2.Response, error) {
+func (c *MQTTCoupler) quit() (jsonrpc2.Response, error) {
 	params := struct {
 		ClientID string `json:"client_id"`
 	}{