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

其他

参考

相关推荐
庸子9 小时前
Ansible & AWX 自动化运维
运维·自动化·ansible
期待のcode10 小时前
图片上传实现
java·前端·javascript·数据库·servlet·交互
吗喽15434518810 小时前
用python实现自动化布尔盲注
数据库·python·自动化
ii_best11 小时前
解锁 iOS 按键精灵辅助工具自动化新可能:iOSElement.Click 让元素交互更简单
运维·自动化
ん贤12 小时前
如何加快golang编译速度
后端·golang·go
天天进步201513 小时前
现代前端开发流程:CI/CD与自动化部署实战
运维·ci/cd·自动化
DogDaoDao13 小时前
GitHub开源轻量级语音模型 Vui:重塑边缘智能语音交互的未来
大模型·github·音视频·交互·vui·语音模型·智能语音
riverz122713 小时前
Go 程序无法使用 /etc/resolv.conf 的 DNS 配置排查记录
golang
nbsaas-boot14 小时前
AI交互的初期魅力与后期维护挑战
人工智能·交互
As_wind_17 小时前
Go 语言学习之测试
开发语言·学习·golang