Golang实现带参数的本地脚本SSH远程执行模拟

Golang实现带参数的本地脚本SSH远程执行模拟 我正在尝试使用Go在远程机器上执行任何类型的本地脚本(sh/bash/python/ruby)或带参数的可执行文件。 ssh命令:ssh user@10.10.10.10 "python3" - < ./test.py "arg1"

package main
import (
    "log"
    "os"

    "golang.org/x/crypto/ssh"
)

func main()  {
    user := "user"
    hostport := "10.10.10.10:22"
    script, _ := os.OpenFile("test.py", os.O_RDWR|os.O_CREATE, 0755)
    interpreter := "python3"
    client, session, err := connectToHost(user, hostport) 
    session.Stdin = script
    session.Stdout = os.Stdout
    err = session.Run(interpreter)
    if err != nil {
        log.Fatal(err)
    }
    client.Close()
    defer session.Close()
}

示例中的ssh命令运行良好,我也能够在远程服务器上执行本地的test.py,但我无法想出任何有效的方法来同时传递参数(例如arg1)。 感谢您的帮助。


更多关于Golang实现带参数的本地脚本SSH远程执行模拟的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

如果我没理解错的话,https://golang.org/pkg/flag/ 是你的最佳选择。可能还有更高级(更简单/功能更全)的选项,但我发现 Go 的方法使用起来极其简单(除非你有极其复杂的参数关系)。

更多关于Golang实现带参数的本地脚本SSH远程执行模拟的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要实现带参数的远程脚本执行,可以通过标准输入传递脚本内容,并在命令中指定参数。以下是修改后的示例:

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "os"

    "golang.org/x/crypto/ssh"
)

func connectToHost(user, hostport string) (*ssh.Client, *ssh.Session, error) {
    // 这里需要实现SSH连接逻辑
    // 示例:使用密码认证
    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password("your-password"),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    
    client, err := ssh.Dial("tcp", hostport, config)
    if err != nil {
        return nil, nil, err
    }
    
    session, err := client.NewSession()
    if err != nil {
        client.Close()
        return nil, nil, err
    }
    
    return client, session, nil
}

func main() {
    user := "user"
    hostport := "10.10.10.10:22"
    
    // 读取本地脚本内容
    scriptContent, err := os.ReadFile("test.py")
    if err != nil {
        log.Fatal(err)
    }
    
    // 创建带参数的远程命令
    interpreter := "python3"
    args := []string{"arg1", "arg2"} // 可以传递多个参数
    remoteCmd := fmt.Sprintf("%s -", interpreter)
    for _, arg := range args {
        remoteCmd += fmt.Sprintf(" %s", arg)
    }
    
    client, session, err := connectToHost(user, hostport)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    defer session.Close()
    
    // 设置标准输入为脚本内容
    session.Stdin = bytes.NewReader(scriptContent)
    session.Stdout = os.Stdout
    session.Stderr = os.Stderr
    
    // 执行远程命令
    err = session.Run(remoteCmd)
    if err != nil {
        log.Fatal(err)
    }
}

另一种更灵活的方法是使用StartStdinPipe

func main() {
    user := "user"
    hostport := "10.10.10.10:22"
    
    scriptContent, err := os.ReadFile("test.py")
    if err != nil {
        log.Fatal(err)
    }
    
    interpreter := "python3"
    args := []string{"arg1", "arg2"}
    
    client, session, err := connectToHost(user, hostport)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    defer session.Close()
    
    session.Stdout = os.Stdout
    session.Stderr = os.Stderr
    
    // 构建命令
    cmd := interpreter + " -"
    for _, arg := range args {
        cmd += " " + arg
    }
    
    // 启动远程命令
    err = session.Start(cmd)
    if err != nil {
        log.Fatal(err)
    }
    
    // 通过管道发送脚本内容
    stdin, err := session.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }
    
    go func() {
        defer stdin.Close()
        io.WriteString(stdin, string(scriptContent))
    }()
    
    // 等待命令完成
    err = session.Wait()
    if err != nil {
        log.Fatal(err)
    }
}

对于二进制可执行文件,可以使用base64编码传输:

import (
    "encoding/base64"
    "strings"
)

func executeBinaryWithArgs(user, hostport, binaryPath string, args []string) error {
    // 读取二进制文件
    binaryContent, err := os.ReadFile(binaryPath)
    if err != nil {
        return err
    }
    
    // base64编码
    encoded := base64.StdEncoding.EncodeToString(binaryContent)
    
    client, session, err := connectToHost(user, hostport)
    if err != nil {
        return err
    }
    defer client.Close()
    defer session.Close()
    
    // 构建远程命令:解码并执行
    remoteCmd := fmt.Sprintf("echo %s | base64 -d | chmod +x /dev/stdin && /dev/stdin", encoded)
    if len(args) > 0 {
        remoteCmd += " " + strings.Join(args, " ")
    }
    
    session.Stdout = os.Stdout
    session.Stderr = os.Stderr
    
    return session.Run(remoteCmd)
}

这些方法可以处理带参数的脚本和可执行文件在远程服务器上的执行。

回到顶部