GoLang执行需要输入密码的命令

需求

  • 同步一组视频到其他节点
  • 限制带宽,防止占用过多带宽对访问造成影响

分析

  • Linux命令scprsync满足需求
  • 使用以上命令都需要输入服务器密码,这里给出2个方案
    • 对各个节点做免密
    • 使用gexpect

免密(推荐)

  • 实例演示服务器用户名为root,IP为192.168.1.208

本地生成公私钥

ssh-keygen (一路回车默认即可)

以上命令会在~/.ssh下创建两个密钥

  • id_rsa (私钥)
  • id_rsa.pub (公钥)

上传公钥

ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.208

以上命令会在服务器的~/.ssh/authorized_keys文件中写入客户端的公钥

### 执行命令同步
前两步已经实现了服务端对客户端的免密,通过ssh root@192.168.1.208进行测试。然后就可以使用os/exec调用系统命令来进行同步,具体代码如下

func main() {
   args := []string{
       "-avz", "--delete",
       "--timeout=60", "--bwlimit=3000",
       "/home/wsl/video/",
       "root@192.168.1.208:/root/wsl/video/",
   }

   cmd := exec.Command("rsync", args...)
   var stdOut, stdErr bytes.Buffer
   cmd.Stderr = &stdErr
   cmd.Stdout = &stdOut
   err := cmd.Run()
   if err != nil {
       log.Fatalf("Got error:%s, msg:%s", err, stdErr.String())
   }
   fmt.Println("success:", stdOut.String())
}

使用gexpect

  • gexpect : https://github.com/ThomasRooney/gexpect
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/ThomasRooney/gexpect"
)

func main() {
    cmd := "rsync -avz -e 'ssh -p 22' --delete --timeout=60 --bwlimit=3000 /home/video root@192.168.1.208:/root/"
    pwd := "yourpassword"
    
    child, err := gexpect.Spawn(cmd)
    if err != nil {
        log.Fatal("Spawn cmd error ", err)
    }

    if err := child.ExpectTimeout("password: ", 10*time.Second); err != nil {
        log.Fatal("Expect timieout error ", err)
    }

    if err := child.SendLine(pwd); err != nil {
        log.Fatal("SendLine password error ", err)
    }

    if err := child.Wait(); err != nil {
        log.Fatal("Wait error: ", err)
    }

    fmt.Println("Success")
}

转载于:https://www.cnblogs.com/mrylong/p/10763428.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值