李治波 發表於 2020-11-27 10:16:00

01-Go连接到Linux服务器进行操作-执行shell命令&&上传文件

<h2 id="go连接到linux服务器进行操作">Go连接到Linux服务器进行操作</h2>
<h3 id="使用密码连接linux服务器">使用密码连接Linux服务器</h3>
<pre><code class="language-go">package main

import (
        "fmt"
        "golang.org/x/crypto/ssh"
        "log"
        "time"
)

func pwdConnect(sshHost, sshUser, sshPassword string, sshPort int) (*ssh.Client, error) {
        // 创建ssh登录配置
        config := &amp;ssh.ClientConfig{
                Timeout:         5 * time.Second,                           // 超时时间
                User:            sshUser,                                     // 登录账号
                Auth:            []ssh.AuthMethod{ssh.Password(sshPassword)}, // 密码
                HostKeyCallback: ssh.InsecureIgnoreHostKey(),               // 这个不够安全,生产环境不建议使用
                //HostKeyCallback: ssh.FixedHostKey(), // 建议使用这种,目前还没研究出怎么使用
        }

        // dial连接服务器
        addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
        Client, err := ssh.Dial("tcp", addr, config)
        if err != nil {
                log.Fatal("连接到服务器失败", err)
                return nil, err
        }

        //defer sshClient.Close()
        return Client, nil
}

func main() {
// 连接到服务器
        conn, err := pwdConnect("192.168.3.121", "root", "123456", 22)
        if err != nil {
                return
        }
        defer conn.Close()

        // 创建 ssh session 会话
        session, err := conn.NewSession()
        if err != nil {
                panic(err)
        }
        defer session.Close()

        // 执行远程命令
        cmd := "cd /tmp/;ls -l; tar -czf test.tar.gz hello.txt test.txt;ls -l"
        cmdInfo, err := session.CombinedOutput(cmd)
        if err != nil {
                panic(err)
        }
        fmt.Println(string(cmdInfo))
}

</code></pre>
<h3 id="使用秘钥连接到linux服务器">使用秘钥连接到Linux服务器</h3>
<pre><code class="language-go">package main

import (
        "fmt"
        "golang.org/x/crypto/ssh"
        "io/ioutil"
        "time"
)

// 使用秘钥连接Linux服务器

// 连接到linux服务器
func keyConnect(sshUser, sshHost, sshKey string, sshPort int) (*ssh.Client, error) {
        // 读取秘钥
        key, err := ioutil.ReadFile(sshKey)
        if err != nil {
                panic("秘钥读取失败")
        }

        // 创建秘钥签名
        // 会拿着秘钥去登录服务器
        signer, err := ssh.ParsePrivateKey(key)
        if err != nil {
                panic("秘钥签名失败")
        }

        // ssh配置
        config := &amp;ssh.ClientConfig{
                Timeout: 5 * time.Second, // 超时时间
                User:    sshUser,
                Auth: []ssh.AuthMethod{
                        // 使用秘钥登录远程服务器
                        ssh.PublicKeys(signer),
                },
                HostKeyCallback: ssh.InsecureIgnoreHostKey(), //这个不够安全,生产环境不建议使用
                //var hostKey ssh.PublicKey
                //HostKeyCallback: ssh.FixedHostKey(hostKey),
        }

        // 连接远程服务器
        addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
        client, err := ssh.Dial("tcp", addr, config)
        if err != nil {
                fmt.Println("连接远程服务器失败", err)
                return nil, err
        }

        //defer client.Close()
        return client, nil
}

func main() {
        // 连接服务器
        conn, err := keyConnect("root", "192.168.3.121", "id_rsa", 22)
        if err != nil {
                panic(err)
        }
        defer conn.Close()

        // 创建 ssh session 会话
        session, err := conn.NewSession()
        if err != nil {
                panic(err)
        }
        defer session.Close()

        // 执行远程命令
        cmd := "cd /tmp/; ls -l"
        cmdInfo, err := session.CombinedOutput(cmd)
        if err != nil {
                panic(err)
        }
        fmt.Println(string(cmdInfo))
}

</code></pre>
<h3 id="使用秘钥或者密码连接到服务器">使用秘钥或者密码连接到服务器</h3>
<pre><code class="language-go">package main

import (
        "errors"
        "fmt"
        "golang.org/x/crypto/ssh"
        "io/ioutil"
        "log"
        "time"
)

func keyOrPwdConnect(sshHost, sshUser, sshPassword, sshKey string, sshPort int) (*ssh.Client, error) {
        // 创建ssh登录配置
        config := &amp;ssh.ClientConfig{
                Timeout:         5 * time.Second,             // 超时时间
                User:            sshUser,                     // 登录账号
                HostKeyCallback: ssh.InsecureIgnoreHostKey(), //这个不够安全,生产环境不建议使用
                //HostKeyCallback: ssh.FixedHostKey(), //建议使用这种
        }

        if sshKey != "" {
    // 秘钥登录
                key, err := ioutil.ReadFile(sshKey) // 读取秘钥
                if err != nil {
                        panic("秘钥读取失败")
                }
                // 创建秘钥签名
                signer, err := ssh.ParsePrivateKey(key)
                if err != nil {
                        panic("秘钥签名失败")
                }
                // 配置秘钥登录
                config.Auth = []ssh.AuthMethod{
                        ssh.PublicKeys(signer),
                }
        } else if sshPassword != "" {
                // 密码登录
                config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
        } else {
                err := errors.New("秘钥或者密码登录")
                return nil, err
        }

        // dial连接服务器
        addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
        Client, err := ssh.Dial("tcp", addr, config)
        if err != nil {
                log.Fatal("连接到服务器失败", err)
                return nil, err
        }

        return Client, nil
}

func main() {
        // 连接服务器
        //conn, err := keyOrPwdConnect("192.168.3.121", "root", "", "id_rsa", 22) // 秘钥登录
        conn, err := keyOrPwdConnect("192.168.3.121", "root", "123456", "", 22) // 密码登录
        if err != nil {
                panic(err)
        }
        defer conn.Close()

        // 创建 ssh session 会话
        session, err := conn.NewSession()
        if err != nil {
                panic(err)
        }
        defer session.Close()

        // 执行远程命令
        cmd := "echo 'hello world!'"
        cmdInfo, err := session.CombinedOutput(cmd)
        if err != nil {
                panic(err)
        }
        fmt.Println(string(cmdInfo))
}

</code></pre>
<p>上传文件到Linux服务器</p>
<pre><code class="language-go">package main

import (
        "errors"
        "fmt"
        "github.com/pkg/sftp"
        "golang.org/x/crypto/ssh"
        "io/ioutil"
        "log"
        "os"
        "path"
        "time"
)

// 通过SSH连接Linux服务器
func keyOrPwdConnectLinuxServer(sshHost, sshUser, sshPassword, sshKey string, sshPort int) (*ssh.Client, error) {
        // 创建ssh登录配置
        config := &amp;ssh.ClientConfig{
                Timeout:         5 * time.Second,             // 超时时间
                User:            sshUser,                     // 登录账号
                HostKeyCallback: ssh.InsecureIgnoreHostKey(), //这个不够安全,生产环境不建议使用
                //HostKeyCallback: ssh.FixedHostKey(), //建议使用这种
        }

       
        if sshKey != "" {
                // 秘钥登录
                key, err := ioutil.ReadFile(sshKey)
                if err != nil {
                        panic("秘钥读取失败")
                }
                // 创建秘钥签名
                // 会拿着秘钥去登录服务器
                signer, err := ssh.ParsePrivateKey(key)
                if err != nil {
                        panic("秘钥签名失败")
                }
                // 配置秘钥登录
                config.Auth = []ssh.AuthMethod{
                        ssh.PublicKeys(signer),
                }
        } else if sshPassword != "" {
                // 密码登录
                config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
        } else {
                err := errors.New("秘钥或者密码登录")
                return nil, err
        }

        // dial连接服务器
        addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
        Client, err := ssh.Dial("tcp", addr, config)
        if err != nil {
                log.Fatal("连接到服务器失败", err)
                return nil, err
        }

        return Client, nil
}

// 创建sftp会话
func CreateSftp(sshHost, sshUser, sshPassword, sshKey string, sshPort int) (*sftp.Client, error) {
        // 连接Linux服务器
        conn, err := keyOrPwdConnectLinuxServer(sshHost, sshUser, sshPassword, sshKey, sshPort)
        if err != nil {
                fmt.Println("连接Linux服务器失败")
                panic(err)
        }
        //defer conn.Close()

        // 创建sftp会话
        client, err := sftp.NewClient(conn)
        if err != nil {
                return nil, err
        }
        //defer client.Close()
        return client, nil
}

func main() {
        // 连接sftp
        client, err := CreateSftp("192.168.3.121", "root", "123456", "", 22)
        if err != nil {
                return
        }
        defer client.Close()

        // 浏览服务器/home/devel目录
        //w := client.Walk("/home/devel")
        //for w.Step() {
        //        if w.Err() != nil {
        //                continue
        //        }
        //        fmt.Println(w.Path())
        //}

        // 在服务器创建文件
        //f, err := client.Create("/tmp/hello.txt")
        //if err != nil {
        //        panic(err)
        //}
        //_, err = f.Write([]byte("hello world!\n")) // 写入内容
        //if err != nil {
        //        panic(err)
        //}
        //f.Close()

        // 查看服务器的文件
        //fi, err := client.Lstat("/tmp/hello.txt")
        //if err != nil {
        //        panic(err)
        //}
        //fmt.Printf("%#v\n", fi)

        // 上传文件
        var localFilePath = "./test.txt" // 本地文件全路径
        var remoteDir = "/tmp"         // 服务器目录
        // 打开需要上传的本地文件
        srcFile, err := os.Open(localFilePath)
        if err != nil {
                panic(err)
        }
        defer srcFile.Close()
        // 获取需要上传的文件的名称
        var remoteFileName = path.Base(localFilePath)
        // 在服务器创建文件并打开文件获得句柄
        dstFile, err := client.Create(path.Join(remoteDir, remoteFileName))
        if err != nil {
                panic(err)
        }
        defer dstFile.Close()
        // 写入内容
        buf := make([]byte, 1024)
        for {
                n, _ := srcFile.Read(buf) // 把文件中的内容读取到buf中,每次读取本地需要上传的文件1024字节内容
                // 当n=0时,证明本地需要上传的文件已经读取完毕了
                if n == 0 {
                        break
                }
                dstFile.Write(buf) // 写入到句柄
        }
        fmt.Println("文件上传完毕")
}

</code></pre>


</div>
<div id="MySignature" role="contentinfo">
    转载请注明出处哟~
https://www.cnblogs.com/lichengguo<br><br>
来源:https://www.cnblogs.com/lichengguo/p/14046505.html
頁: [1]
查看完整版本: 01-Go连接到Linux服务器进行操作-执行shell命令&&上传文件