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响应。下面是修正后的代码:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "golang.org/x/crypto/ssh"
  6. "io/ioutil"
  7. "os"
  8. "github.com/gin-gonic/gin"
  9. )
  10. func main() {
  11. r := gin.Default()
  12. // 定义POST路由 /execute
  13. r.POST("/execute", func(c *gin.Context) {
  14. command := c.PostForm("command") // 从请求中获取命令参数
  15. if len(command) == 0 {
  16. c.JSON(400, gin.H{"error": "Command parameter is required"})
  17. return
  18. }
  19. output, err := executeSSHCommand(command) // 执行SSH命令
  20. if err != nil {
  21. c.JSON(500, gin.H{"error": err.Error()})
  22. return
  23. }
  24. c.JSON(200, gin.H{"output": output})
  25. })
  26. r.Run(":8080")
  27. }
  28. func executeSSHCommand(cmd string) (string, error) {
  29. remoteAddr := "<remote-server-address>"
  30. sshPort := 22
  31. auth := []ssh.AuthMethod{ssh.Password("<your-password>")}
  32. config := &ssh.ClientConfig{
  33. User: "<your-username>",
  34. Auth: auth,
  35. HostKeyCallback: ssh.InsecureIgnoreHostKey(),
  36. }
  37. conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", remoteAddr, sshPort), config)
  38. if err != nil {
  39. return "", err
  40. }
  41. defer conn.Close()
  42. session, err := conn.NewSession()
  43. if err != nil {
  44. return "", err
  45. }
  46. defer session.Close()
  47. stdout, err := session.StdoutPipe()
  48. if err != nil {
  49. return "", err
  50. }
  51. stdin, err := session.StdinPipe()
  52. if err != nil {
  53. return "", err
  54. }
  55. scanner := bufio.NewScanner(stdout)
  56. // 创建一个带缓冲区的通道来获取实际输出
  57. outputChan := make(chan string, 100)
  58. // 在协程中从标准输出流中读取数据并将其发送到通道中
  59. go func() {
  60. for scanner.Scan() {
  61. outputChan <- scanner.Text()
  62. }
  63. if scanner.Err() != nil {
  64. fmt.Println(scanner.Err())
  65. close(outputChan)
  66. return
  67. }
  68. close(outputChan)
  69. }()
  70. _, _ = stdin.Write([]byte(cmd + "\n"))
  71. var output string
  72. // 等待通道关闭并读取其中的所有数据作为API响应。
  73. for line := range outputChan {
  74. output += line + "\n"
  75. }
  76. // 等待命令执行完成,然后返回错误信息(如果有)
  77. if waitErr := session.Wait(); waitErr != nil {
  78. return output, waitErr
  79. }
  80. // 如果没有错误,则返回实际输出
  81. return output, nil
  82. }

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

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

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?