简介
基于上篇 Golang实现一个批量自动化执行树莓派指令的软件(5)模块整合, 这里我们实现简单的从配置文件设置指令集, 然后程序自动运行指令集的操作。
环境描述
运行环境: Windows, 基于Golang, 暂时没有使用什么不可跨平台接口, 理论上支持Linux/MacOS
目标终端:树莓派DebianOS(主要做用它测试)
实现
package controller
import (
"encoding/json"
"fmt"
"os"
"ssh_remote_access/app"
"ssh_remote_access/models"
"ssh_remote_access/sshutil"
"ssh_remote_access/utils"
"sync"
"time"
)
type JobController struct {
settings models.Settings
sshutil *sshutil.SSHUtil
}
func NewJobController(decryptionKey string, cfgPath string) (*JobController, error) {
var (
controller = &JobController{}
err error
encrypt *utils.Encryption
realPassword string
)
/* 加载文件 */
if err = controller.loadConfig(cfgPath); nil != err {
return nil, err
}
/* 组合配置信息 */
encrypt = utils.NewEncryption(decryptionKey)
if realPassword, err = encrypt.Decrypt(controller.settings.User.Password); nil != err {
return nil, err
}
controller.sshutil, err = sshutil.NewSSHUtil(sshutil.SSHConfig{
IP: controller.settings.Network.IP,
Port: controller.settings.Network.Port,
Timeout: controller.settings.Network.Timeout,
User: controller.settings.User.Name,
Password: realPassword,
})
return controller, err
}
func RunJobList() error {
var (
controller *JobController
err error
)
/* 初始化任务列表 */
controller, err = NewJobController(app.ASE_KEY, app.CONFIG_PATH)
if nil != err {
fmt.Println("run job list fail, ", err.Error())
return err
}
defer controller.Destroy()
/* 执行任务 */
err = controller.RunJobs(func(currFinishedJob models.SSHJob, jobNum, fnishedNum uint) error {
fmt.Printf("job_type: %d, total job: %d, finished job: %d.\n", currFinishedJob.Type, jobNum, fnishedNum)
return nil
})
return err
}
func (j *JobController) Destroy() error {
return j.sshutil.Destroy()
}
func (j *JobController) loadConfig(filepath string) error {
var bs, err = os.ReadFile(filepath)
if nil != err {
return err
}
err = json.Unmarshal(bs, &j.settings)
return err
}
func (j *JobController) RunJobs(processCallback func(currFinishedJob models.SSHJob, jobNum, fnishedNum uint) error) error {
var (
waiter sync.WaitGroup
err error
)
for i, job := range j.settings.JobList {
waiter.Add(1)
time.Sleep(time.Duration(job.BeforeSleep) * time.Millisecond)
switch models.SSH_TYPE(job.Type) {
case models.SSH_COMMAND:
_, err = j.sshutil.Commander().Command(job.Command)
if nil != err {
return err
}
case models.SSH_UPLOAD:
err = j.sshutil.SFTFClient().UploadWithCallback(job.From, job.To, func(from, to string, num, uploaded uint) {
fmt.Println("upload from ", from, " to ", to, ", total_num ", num, " upload_num ", uploaded)
}, func(err error) {
fmt.Println("upload finished")
}, false)
if nil != err {
return err
}
case models.SSH_DOWNLOAD:
err = j.sshutil.SFTFClient().DownloadWithCallback(job.From, job.To, func(from, to string, num, downloaded uint) {
fmt.Println("download from ", from, " to ", to, ", total_num ", num, " download_num ", downloaded)
}, func(err error) {
fmt.Println("download finished")
}, false)
if nil != err {
return err
}
}
time.Sleep(time.Duration(job.AfterSleep) * time.Millisecond)
if err = processCallback(job, uint(len(j.settings.JobList)), uint(i+1)); nil != err {
}
}
return err
}
测试用例
代码源
https://gitee.com/grayhsu/ssh_remote_access
视频
Golang实现远程ssh访问-简单批量化指令示例