ZBLOG

package main import ( "bufio" "fmt" "golang.org/x/crypto/ssh" "io/ioutil" "os" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // 定义POST

这段代码中的executeSSHCommand函数会在启动一个协程后立即返回”Command executed successfully”,而不是等待远程命令执行完成并返回实际输出。因此,最终的API响应总是{"output": "Command executed successfully"},无论远程命令是否成功执行。

要解决这个问题,可以使用一个带有缓冲区的通道来获取实际输出,并在协程中从标准输出流中读取数据并将其发送到通道中。然后,在主函数中等待通道关闭并读取其中的所有数据作为API响应。下面是修正后的代码:

package main

import (
    "bufio"
    "fmt"
    "golang.org/x/crypto/ssh"
    "io/ioutil"
    "os"

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()

    // 定义POST路由 /execute
    r.POST("/execute", func(c *gin.Context) {
        command := c.PostForm("command") // 从请求中获取命令参数

        if len(command) == 0 {
            c.JSON(400, gin.H{"error": "Command parameter is required"})
            return
        }

        output, err := executeSSHCommand(command) // 执行SSH命令

        if err != nil {
            c.JSON(500, gin.H{"error": err.Error()})
            return
        }

        c.JSON(200, gin.H{"output": output})
    })

    r.Run(":8080")
}

func executeSSHCommand(cmd string) (string, error) {
    remoteAddr := "<remote-server-address>"
    sshPort := 22

    auth := []ssh.AuthMethod{ssh.Password("<your-password>")}

    config := &ssh.ClientConfig{
        User:            "<your-username>",
        Auth:            auth,
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }

    conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", remoteAddr, sshPort), config)

    if err != nil {
        return "", err
    }

    defer conn.Close()

    session, err := conn.NewSession()

    if err != nil {
        return "", err
    }

    defer session.Close()

    stdout, err := session.StdoutPipe()

    if err != nil {
        return "", err
    }

    stdin, err := session.StdinPipe()

    if err != nil {
        return "", err
    }

    scanner := bufio.NewScanner(stdout)
    
	// 创建一个带缓冲区的通道来获取实际输出
	outputChan := make(chan string, 100)

	// 在协程中从标准输出流中读取数据并将其发送到通道中
	go func() {
		for scanner.Scan() {
			outputChan <- scanner.Text()
		}
		
		if scanner.Err() != nil {
			fmt.Println(scanner.Err())
			close(outputChan)
			return
		}
		
		close(outputChan)
	}()

	_, _ = stdin.Write([]byte(cmd + "\n"))

	var output string
	
	// 等待通道关闭并读取其中的所有数据作为API响应。
	for line := range outputChan {
	    output += line + "\n"
   }
   
   // 等待命令执行完成,然后返回错误信息(如果有)
   if waitErr := session.Wait(); waitErr != nil {
       return output, waitErr
   }
   
   // 如果没有错误,则返回实际输出
   return output, nil
}

在上面的代码中,我们创建了一个带缓冲区的通道outputChan来获取实际输出。在协程中,我们从标准输出流中读取数据并将其发送到通道中。在主函数中,我们等待通道关闭并读取其中的所有数据作为API响应。最后,在等待命令执行完成之后,我们检查是否有任何错误,并根据需要返回它们。

注意:该修复代码没有处理超时、连接失败和其他异常情况,需要根据具体情况进行修改。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=4567

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?