需求
- 同步一组视频到其他节点
- 限制带宽,防止占用过多带宽对访问造成影响
分析
- Linux命令
scp
,rsync
满足需求 - 使用以上命令都需要输入服务器密码,这里给出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 mainimport ( "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")}