Golang实现一个批量自动化执行树莓派指令的软件(1)文本加密&配置&命令行交互实现

简介

实现一个在配置文件设置信息,一运行就可以自动执行设定指令的软件。

这次实现的是 :
1. 加密解密模块, 用于加密密码, 在配置时配置已加密的密码就可以;
2. 需要配置,自然也就有配置文件的序列化反序列化;
3. 这么多操作如果都放到一个文件执行就需要命令行指令知道当前该执行的动作, 所以还有个命令行交互

环境描述

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

实现

加密解密

cpp 复制代码
package utils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"io"
)

type Encryption struct {
	Key []byte
}

func NewEncryption(key string) *Encryption {
	return &Encryption{Key: []byte(key)}
}

func (e *Encryption) Encrypt(text string) (string, error) {
	block, err := aes.NewCipher(e.Key)
	if err != nil {
		return "", err
	}
	textBytes := []byte(text)
	// 对于CBC模式,需要使用PKCS#7填充plaintext到blocksize的整数倍
	textBytes = e.pad(textBytes, aes.BlockSize)
	ciphertext := make([]byte, aes.BlockSize+len(textBytes))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return "", err
	}
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], textBytes)
	return base64.StdEncoding.EncodeToString(ciphertext), nil
}

func (e *Encryption) Decrypt(text string) (string, error) {
	data, err := base64.StdEncoding.DecodeString(text)
	if err != nil {
		return "", err
	}
	block, err := aes.NewCipher(e.Key)
	if err != nil {
		return "", err
	}
	if len(data) < aes.BlockSize {
		return "", err
	}
	iv := data[:aes.BlockSize]
	data = data[aes.BlockSize:]
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(data, data)
	data = e.unpad(data, aes.BlockSize)
	return string(data), nil
}

// pad 使用PKCS#7标准填充数据
func (e *Encryption) pad(buf []byte, blockSize int) []byte {
	padding := blockSize - (len(buf) % blockSize)
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(buf, padtext...)
}

// unpad 移除PKCS#7标准填充的数据
func (e *Encryption) unpad(buf []byte, blockSize int) []byte {
	if len(buf)%blockSize != 0 {
		return nil
	}
	padding := int(buf[len(buf)-1])
	return buf[:len(buf)-padding]
}

配置

isettings.go

cpp 复制代码
package utils

import (
	"errors"
)

type SettingsType int

const (
	SETTINGS_JSON SettingsType = 0
)

type ISettings interface {
	FromBytes(src []byte) error
	ToBytes() ([]byte, error)

	FromFile(filepath string) error
	ToFile(filepath string) error

	Data() interface{}
}

func NewSettings(typ SettingsType, model interface{}) (ISettings, error) {
	if nil == model {
		return nil, errors.New("model == nil")
	}
	switch typ {
	case SETTINGS_JSON:
		return NewJsonSettings(model)
	default:
		return nil, errors.New("wrong setting type")
	}
}

jsonsettings.go

go 复制代码
package utils

import (
	"encoding/json"
	"os"
)

type JsonSettings struct {
	dat interface{}
}

func NewJsonSettings(v interface{}) (ISettings, error) {
	cfg := &JsonSettings{dat: v}
	return cfg, nil
}

func (c *JsonSettings) FromBytes(src []byte) error {
	return json.Unmarshal(src, c.dat)
}

func (c *JsonSettings) ToBytes() ([]byte, error) {
	return json.MarshalIndent(c.dat, "", "  ")
}

func (c *JsonSettings) FromFile(filepath string) error {
	bs, err := os.ReadFile(filepath)
	if nil != err {
		return err
	}
	err = c.FromBytes(bs)
	return err
}

func (c *JsonSettings) ToFile(filepath string) error {
	bs, err := c.ToBytes()
	if nil != err {
		return err
	}
	err = os.WriteFile(filepath, bs, 0666)

	return err
}

func (c *JsonSettings) Data() interface{} {
	return c.dat
}

命令行交互

go 复制代码
package cmd

import (
	"github.com/spf13/cobra"
	"os"
)

var rootCommand = rootCmd()

/*
所有指令初始化
*/
func init() {
	rootCommand.AddCommand(runCmd())
	rootCommand.AddCommand(versionCmd())
	rootCommand.AddCommand(initCmd())
	rootCommand.AddCommand(encryptCmd())
}

func rootCmd() *cobra.Command {
	var cmd = &cobra.Command{
		Use:   "ssh_remote_access",
		Short: "SSH Remote Access Tool",
		Long:  "SSH Remote Access Tool, get help from https://listentome.blog.csdn.net/",
		Run:   rootRun,
	}
	cmd.Flags().BoolP("run", "r", false, "run job list")
	cmd.Flags().BoolP("init", "i", false, "initialize the tool")
	cmd.Flags().BoolP("version", "v", false, "get version")
	cmd.Flags().StringP("encrypt", "e", "", "encrypt the string")
	return cmd
}

func rootRun(cmd *cobra.Command, args []string) {
	var cmdStrings = []string{"run", "init", "version", "encrypt"}

	var matchCmd string
	for _, v := range cmdStrings {
		var flag = cmd.Flag(v)
		if flag != nil && flag.Changed {
			matchCmd = v
			break
		}
	}

	if matchCmd == "" {
		matchCmd = "help"
		cmd.Help()
		return
	}

	for _, v := range cmd.Commands() {
		if v.Name() == matchCmd {
			v.Run(cmd, args)
			return
		}
	}
}

func Execute() error {
	rootCommand.SetArgs(os.Args[1:])
	return rootCommand.Execute()
}

代码源

https://gitee.com/grayhsu/ssh_remote_access

其他

参考

相关推荐
Chrikk20 分钟前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*22 分钟前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue23 分钟前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man25 分钟前
【go从零单排】go语言中的指针
开发语言·后端·golang
Jason-河山3 小时前
【自动化更新,让商品信息跳舞】——利用API返回值的幽默编程之旅
运维·自动化
有梦想的咸鱼_4 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
海阔天空_20134 小时前
Python pyautogui库:自动化操作的强大工具
运维·开发语言·python·青少年编程·自动化
桥田智能4 小时前
气爪在自动化装配线中是如何应用的?
运维·自动化
天郁青5 小时前
数据库交互的本地项目:后台管理系统
数据库·交互
Tassel_YUE6 小时前
网络自动化04:python实现ACL匹配信息(主机与主机信息)
网络·python·自动化