大项目笔记3 | 青训营笔记

89 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第7天

今日成果

ssh服务器

搭建: www.bilibili.com/video/BV1rz…

ffmpeg : sudo snap install ffmpeg

wpy云服务器上:sudo apt-get install ffmpeg

ssh和ffmpeg 配置好之后检查是否成功

搭建环境是否成功测试 :

1.修改config.go文件下变量Ssh_addr_port、Ssh_username、Ssh_password为自己服务器对应的参数

2.创建config.go文件下变量Ftp_video_path、Ftp_image_path对应的路径(可自己定义)

3.将data目录下的bear.mp4文件存放在config.go文件的Ftp_video_path变量记录的路径下

4.cd到ffmpeg文件夹下 go test

5.Ftp_image_path路径下出现bear.jpg和bear2.jpg文件 则配置成功

openssl采用口令方式登陆,服务器提供公钥给客户端,客户端用公钥加密自己的密码后发回,服务器用私钥解密验证

openssl默认60s断开连接,因此需要加入应用层客户端心跳。

当前实现客户端方未验证服务器公钥是否正确,若实际生产环境需得到服务器公钥到配置文件中,防止中间人截获并伪装服务器

type Ffmsg struct {
	VideoName string
	ImageName string
}

var ClientSSH *ssh.Client
var Ffchan chan Ffmsg

func Init() {
	var err error
	clientConfig := &ssh.ClientConfig{
		Timeout: time.Second * 5, //最多5s建立连接
		User:    config.Ssh_username,
		Auth: []ssh.AuthMethod{
			ssh.Password(config.Ssh_password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), //不检查公钥
	}
	ClientSSH, err = ssh.Dial("tcp", config.Ssh_addr_port, clientConfig)
	if err != nil {
		log.Fatal("Failed to dial: ", err)
	}

	Ffchan = make(chan Ffmsg, config.Ssh_max_taskCnt)
	go dispatcher()
	go keepalive()
	log.Println("ssh初始化成功")
}

// 将ffmpeg命令以及其参数通过ssh运行,若运行失败,则重新放入channel运行
func dispatcher() {
	for ffmsg := range Ffchan {
		go func(f Ffmsg) {
			err := Ffmpeg(f.VideoName, f.ImageName)
			if err != nil {
				Ffchan <- f
				log.Println("ffmpeg调用失败,等待重新执行")
			}
		}(ffmsg)
	}
}

func Ffmpeg(videoName, imageName string) error {
	// Each ClientConn can support multiple interactive sessions,
	// represented by a Session.
	session, err := ClientSSH.NewSession()
	if err != nil {
		log.Fatal("Failed to create session: ", err)
	}
	defer session.Close()

	// Once a Session is created, you can execute a single command on
	// the remote side using the Run method.
	var b bytes.Buffer
	session.Stdout = &b

	if err := session.Run("ffmpeg -ss 00:00:01 -i " + config.Ftp_video_path + videoName + ".mp4 -vframes 1 " + config.Ftp_image_path + imageName + ".jpg"); err != nil {
		log.Println("SSH failed to run: " + err.Error())
		log.Println("远端输出错误信息 : ", b.String())
		return err
	}
	log.Println("ffmpeg 执行成功")
	return nil
}

// openssl 默认为60s断开连接, 因此设置10s一次心跳
func keepalive() {
	for {
		s, err := ClientSSH.NewSession()
		if err != nil {
			log.Println("ssh连接断开! err : ", err)
		}
		time.Sleep(10 * time.Second)
		s.Close()
	}
}