1 bat_ssh.go

package main

import (
   "bufio"
   "fmt"
   "golang.org/x/crypto/ssh"
   "log"
   "os"
   "strings"
   "sync"
)

func sshCommand(hostname, port, username, password string, commands []string) {
   // 配置 SSH 客户端
   config := &ssh.ClientConfig{
      User: username,
      Auth: []ssh.AuthMethod{
         ssh.Password(password),
      },
      HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 不验证主机密钥(仅用于测试)
   }
   log.Printf("starting %v >>>>", hostname)
   // 连接到 SSH 服务器
   client, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", hostname, port), config)
   if err != nil {
      fmt.Printf("Failed to dial: %s\n", err)
      return
   }
   defer client.Close()

   // 创建会话
   session, err := client.NewSession()
   if err != nil {
      fmt.Printf("Failed to create session: %s\n", err)
      return
   }
   defer session.Close()

   // 执行命令
   for _, command := range commands {
      // 创建新的会话
      session, err := client.NewSession()
      if err != nil {
         fmt.Println("Failed to create session:", err)
         return
      }
      defer session.Close()
      output, err := session.Output(command)
      if err != nil {
         fmt.Printf("Failed to run command '%s': %s\n", command, err)
         return
      }
      fmt.Printf("Output from command '%s':\n%s\n", command, output)
   }
   //fmt.Println(strings.Repeat("=", 40))
   fmt.Println("End of output")
}

func readSSHInfo(filePath string) ([][4]string, error) {
   var sshInfo [][4]string
   file, err := os.Open(filePath)
   if err != nil {
      return nil, err
   }
   defer file.Close()

   scanner := bufio.NewScanner(file)
   for scanner.Scan() {
      line := strings.TrimSpace(scanner.Text())
      if line != "" {
         parts := strings.Split(line, "----")
         if len(parts) == 4 {
            sshInfo = append(sshInfo, [4]string{parts[0], parts[1], parts[2], parts[3]})
         } else {
            fmt.Printf("Invalid line in file: %s\n", line)
         }
      }
   }

   if err := scanner.Err(); err != nil {
      return nil, err
   }
   return sshInfo, nil
}

// readLines 读取指定文件的内容,并返回每行的切片
func readLines(filePath string) ([]string, error) {
   var lines []string

   // 打开文件
   file, err := os.Open(filePath)
   if err != nil {
      return nil, err
   }
   defer file.Close() // 确保文件在最后关闭

   // 创建一个扫描器逐行读取文件
   scanner := bufio.NewScanner(file)
   for scanner.Scan() {
      line := scanner.Text()      // 获取当前行的内容
      lines = append(lines, line) // 将行添加到切片中
   }

   // 检查扫描过程中是否出现错误
   if err := scanner.Err(); err != nil {
      return nil, err
   }

   return lines, nil
}

func main() {
   // SSH 信息文件路径
   sshInfoFile := "ssh_info.txt"
   commands, err := readLines("command.txt")
   if err != nil {
      fmt.Printf("Error reading commands: %s\n", err)
      return
   }

   // 读取 SSH 信息
   sshInfoList, err := readSSHInfo(sshInfoFile)
   if err != nil {
      fmt.Printf("Error reading SSH info: %s\n", err)
      return
   }

   // 批量登录并执行命令
   var wg sync.WaitGroup
   for _, info := range sshInfoList {
      wg.Add(1)
      go func() {
         defer wg.Done()
         sshCommand(info[0], info[1], info[2], info[3], commands)
      }()
   }
   wg.Wait()
}

2 ssh_info.txt

195.1.1.1----22----root----k122ssaaffw8

3 command.txt

ls -la
ip addr
ping -c 4 8.8.8.8

微信图片_20241025161726.png

https://github.com/zhtest000/bat_ssh/