Golang实现一个批量自动化执行树莓派指令的软件(2)指令

这篇具有很好参考价值的文章主要介绍了Golang实现一个批量自动化执行树莓派指令的软件(2)指令。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

基于上篇 Golang实现一个批量自动化执行树莓派指令的软件(1)文本加密&配置&命令行交互实现, 这篇实现的是指令, 即通过ssh执行linux指令的实现。

环境描述

运行环境: Windows, 基于Golang, 暂时没有使用什么不可跨平台接口, 理论上支持Linux/MacOS
目标终端:树莓派DebianOS(主要做用它测试)

实现

接口定义

type ICommander interface {
	/*
		Command: 堵塞直到执行完毕
	*/
	Command(cmdStr string) (output string, err error)
	/*
		CommandWithCallback:
			background 为 true 时 异步函数, 执行完毕之后自动调用回调
			background 为 false时 堵塞直到执行完毕之后调用回调
	*/
	CommandWithCallback(cmdStr string, callback func(output string, err error), background bool) error

	/*
		Cancel : 任务取消, 执行到一半的任务断开场景
	*/
	Cancel() error

	/*
		Desroy : 无论如何直接关闭客户端
	*/
	Destroy() error
}

接口实现

package sshutil

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

type Commander struct {
	sshClient *ssh.Client

	started  bool
	canceled chan struct{}
	finished chan struct{}
}

func NewCommander(cfg SSHConfig) (*Commander, error) {
	sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", cfg.IP, cfg.Port), cfg.sshClientConfig)
	if err != nil {
		return nil, err
	}
	return &Commander{
		sshClient: sshClient,
		canceled:  make(chan struct{}),
		finished:  make(chan struct{}),
	}, nil
}

func (c *Commander) Command(cmd string) (output string, err error) {
	c.doCommand(cmd, func(recvStr string, e error) {
		output = recvStr
		err = e
	})
	return
}

func (c *Commander) CommandWithCallback(cmd string, callback func(output string, e error), background bool) (err error) {
	if background {
		go c.doCommand(cmd, callback)
	} else {
		c.doCommand(cmd, callback)
	}
	return
}

func (c *Commander) doCommand(cmd string, callback func(output string, e error)) {
	var (
		session   *ssh.Session
		recvBytes []byte
		err       error
		canceled  bool
	)

	if session, err = c.sshClient.NewSession(); err != nil {
		callback("", err)
		return
	}
	c.started = true

	go func(session *ssh.Session) {
		select {
		case <-c.finished:
		case <-c.canceled:
			canceled = true
			if e := session.Signal(ssh.SIGINT); nil != err {
				fmt.Println("emit abort fail: ", e.Error())
			}
		}
	}(session)

	defer func() {
		c.started = false
		if !canceled {
			c.finished <- struct{}{}
		}
		if e := session.Close(); nil != e && e != io.EOF {
			fmt.Println("session close fail: ", e.Error())
		}
	}()

	// err = session.Start(command) // ssh库的异步方式
	if recvBytes, err = session.CombinedOutput(cmd); err != nil {
		if canceled {
			err = fmt.Errorf("user canceled")
		}
		callback(string(recvBytes), err)
		return
	}

	callback(string(recvBytes), err)
}

func (c *Commander) Cancel() error {
	if c.started {
		select {
		case c.canceled <- struct{}{}:
		case <-time.After(time.Second): // 取消时间过长,取消失败
			return fmt.Errorf("time out waiting for cancel")
		}
	}
	return nil
}

func (c *Commander) Destroy() error {
	var err = c.Cancel()
	close(c.finished)
	close(c.canceled)
	err = c.sshClient.Close()
	return err
}

测试用例

package sshutil

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

func newCommander() (*Commander, error) {
	config := &ssh.ClientConfig{
		User: "pi",
		Auth: []ssh.AuthMethod{
			ssh.Password("a123456"),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}
	sshCfg := SSHConfig{
		IP:              "192.168.3.2",
		Port:            22,
		User:            "pi",
		Password:        "a123456",
		sshClientConfig: config,
	}
	commander, err := NewCommander(sshCfg)

	return commander, err
}

func TestEasyCommandAndDestroy(t *testing.T) {
	commander, err := newCommander()
	if nil != err {
		fmt.Println("new command fail: ", err.Error())
		return
	}
	defer func() {
		e := commander.Destroy()
		if nil != err {
			fmt.Println("fail to destroy, ", e.Error())
		}
	}()
	var output string
	output, err = commander.Command("ls /")
	fmt.Println("command result: ", output)
}

func TestCommandWithCallbackWithoutAsync(t *testing.T) {
	commander, err := newCommander()
	if nil != err {
		fmt.Println("new command fail: ", err.Error())
		return
	}
	defer func() {
		e := commander.Destroy()
		if nil != err {
			fmt.Println("fail to destroy, ", e.Error())
		}
	}()

	err = commander.CommandWithCallback("sleep 4; ls /", func(output string, e error) {
		if nil != e {
			fmt.Println("fail, ", e.Error())
		} else {
			fmt.Println("result: ", output)
		}
	}, false)
	if nil != err {
		fmt.Println("do command fail: ", err.Error())
		return
	}
}

func TestCommandWithCallbackAsync(t *testing.T) {
	var waiter sync.WaitGroup
	commander, err := newCommander()
	if nil != err {
		fmt.Println("new command fail: ", err.Error())
		return
	}
	defer func() {
		e := commander.Destroy()
		if nil != err {
			fmt.Println("fail to destroy, ", e.Error())
		}
	}()
	waiter.Add(1)
	err = commander.CommandWithCallback("sleep 4; ls /", func(output string, e error) {
		if nil != e {
			fmt.Println("fail, ", e.Error())
		} else {
			fmt.Println("result: ", output)
		}
		waiter.Done()
	}, true)
	if nil != err {
		fmt.Println("do command fail: ", err.Error())
		return
	}
	fmt.Println("waiting finished<--------")
	waiter.Wait()
	fmt.Println("waiting finished------>")
}

func TestCommandWithCallbackAndCancel(t *testing.T) {
	var waiter sync.WaitGroup
	commander, err := newCommander()
	if nil != err {
		fmt.Println("new command fail: ", err.Error())
		return
	}
	defer func() {
		e := commander.Destroy()
		if nil != err {
			fmt.Println("fail to destroy, ", e.Error())
		}
	}()
	waiter.Add(1)
	err = commander.CommandWithCallback("sleep 10; ls /", func(output string, e error) {
		if nil != e {
			fmt.Println("fail, ", e.Error())
		} else {
			fmt.Println("result: ", output)
		}
		waiter.Done()
	}, true)
	if nil != err {
		fmt.Println("do command fail: ", err.Error())
		return
	}
	fmt.Println("waiting finished<--------")
	time.Sleep(time.Second * 2)
	fmt.Println("canceling...")
	fmt.Println("canceled, ", commander.Cancel())
	waiter.Wait()
	fmt.Println("waiting finished------>")
}

代码源

https://gitee.com/grayhsu/ssh_remote_access文章来源地址https://www.toymoban.com/news/detail-859442.html

其他

参考

到了这里,关于Golang实现一个批量自动化执行树莓派指令的软件(2)指令的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 批量自动化获取电商平台数据的实现方式有哪些?

    随着电子商务的迅猛发展,电商平台的数据日益丰富和多样化。对于许多企业和个人而言,这些数据具有重要的商业价值。因此,如何批量自动化地获取电商平台数据成为了一个热门话题。本文将探讨批量自动化获取电商平台数据的实现方式,并从技术角度进行分析。 爬虫技

    2024年02月04日
    浏览(39)
  • 如何实现批量获取电商数据自动化商品采集?如何利用电商数据API实现业务增长?

    随着电子商务的快速发展,数据已经成为了电商行业最重要的资产之一。在这个数据驱动的时代,电商数据API(应用程序接口)的作用日益凸显。通过电商数据API,商家能够获取到大量关于消费者行为、产品表现、市场趋势等有价值的信息,进而利用这些数据优化业务策略,

    2024年02月19日
    浏览(38)
  • 【AltWalker】模型驱动:轻松实现自动化测试用例的自动生成和组织执行

    模型驱动的自动化测试(Model-Based Testing, 后文中我们将简称为MBT)是一种软件测试方法,它将系统的行为表示为一个或多个模型,然后从模型中自动生成和执行测试用例。这种方法的核心思想是将测试过程中的重点从手动编写测试用例转移到创建和维护描述系统行为的模型。

    2024年02月15日
    浏览(38)
  • 【AltWalker】模型驱动:轻松实现自动化测试用例的生成和组织执行

    模型驱动的自动化测试(Model-Based Testing, 后文中我们将简称为MBT)是一种软件测试方法,它将系统的行为表示为一个或多个模型,然后从模型中自动生成和执行测试用例。这种方法的核心思想是将测试过程中的重点从手动编写测试用例转移到创建和维护描述系统行为的模型。

    2024年02月15日
    浏览(60)
  • 【Golang 接口自动化00】为什么要用Golang做自动化?

    目录 为什么使用Golang做自动化 最终想实现的效果 怎么做? 写在后面  资料获取方法 顺应公司的趋势学习了Golang之后,因为没有太多时间和项目来实践,怕止步于此、步Java缺少练习遗忘殆尽的后尘,决定利用工作之余的时间把此前用Python的写的自动化使用golang进行重构。

    2024年02月15日
    浏览(51)
  • 使用Python+selenium实现第一个自动化测试脚本

    这篇文章主要介绍了使用Python+selenium实现第一个自动化测试脚本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 最近在学web自动化,记录一下学习过程。 此处我选用python3.6+selenium3.0,均用

    2024年02月03日
    浏览(40)
  • 【Golang 接口自动化05】使用yml管理自动化用例

    目录 YAML 基本语法 对象:键值对的集合(key:value) 数组:一组按顺序排列的值 字面量:单个的、不可再分的值(数字、字符串、布尔值) yml 格式的测试用例 定义yml文件 创建结构体 读取yml文件中的用例数据 调试运行 总结 资料获取方法 我们在前面几篇文章中学习怎么发送数

    2024年02月14日
    浏览(30)
  • 软件测试Pytest实现接口自动化应该如何在用例执行后打印日志到日志目录生成日志文件?

    Pytest可以使用内置的logging模块来实现接口自动化测试用例执行后打印日志到日志目录以生成日志文件。以下是实现步骤: 1、在pytest配置文件(conftest.py)中,定义一个日志输出路径,并设置logging模块。 2、在测试用例中调用logging模块,输入需要生成的日志信息。 3、运行p

    2024年02月10日
    浏览(45)
  • 20个Golang自动化DevOps库

    探索 20 个用于简化任务和提高生产力的重要库。 Golang,也称为 Go,是一种静态类型、编译型编程语言,由 Google 的 Robert Griesemer、Rob Pike 和 Ken Thompson 设计。它于 2009 年推出,旨在解决其他编程语言的缺点,特别是在并发编程、垃圾收集和代码可维护性方面。 Golang 拥有众多优

    2024年02月14日
    浏览(33)
  • Selenium批量自动化获取并下载图片

    Selenium批量自动化获取并下载图片 在现代的Web开发中,自动化测试和数据抓取已经成为不可或缺的一部分。Selenium作为一款强大的自动化测试工具,不仅可以用于测试Web应用,还可以用于批量获取网页上的图片。本文将介绍如何使用Selenium批量自动化获取并下载图片。 一、准

    2024年01月22日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包