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

其他

参考

相关推荐
努力的悟空2 小时前
国土变更调查拓扑错误自动化修复工具的研究
运维·自动化
hummhumm2 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
hummhumm2 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
YMWM_3 小时前
第一章 Go语言简介
开发语言·后端·golang
hummhumm4 小时前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
好奇的菜鸟4 小时前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang
Alive~o.04 小时前
Go语言进阶&依赖管理
开发语言·后端·golang
狸克先生5 小时前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
zhd15306915625ff5 小时前
库卡机器人维护需要注意哪些事项
安全·机器人·自动化
skywalk81636 小时前
树莓派2 安装raspberry os 并修改成固定ip
linux·服务器·网络·debian·树莓派·raspberry