我们在使用golang的使用往往会使用配置文件进行配置项的管理,那么我们该怎样具体操作配置文件呢,先上一段代码。
#先看一下我这个demo的结构,很简单,主要就是读取一下配置文件。
[root@ecs-431f-0001 file]# tree
.
├── cmd
│ ├── main.go
├── conf
│ └── conf.ini
├── docker
│ └── commonAnnotation.war
├── go.mod
├── go.sum
└── utils
├── execs
│ └── exec.go
└── setting
└── setting.go
6 directories, 9 files
说一下我这个demo完成的工作:
1、对配置文件的中的配置项进行读取
2、将读取到的配置项读取并且连接到SSH,操作Linux的中命令。
先了解一下ini配置文件
- INI配置文件有三要素
parameters
sectionssectionsparameterscomments
[ssh] #该名称要和下面mapTo中section名称相对应,必须是[]
HostIp = 117.78.5.222
User = root
Password = Yuantong11
Port = 22
Type=password
package setting
import (
"gopkg.in/ini.v1"
"log"
"runtime"
"time"
)
//定义全局配置文件*.ini
var cfg *ini.File
//定义结构体
type SSHServer struct {
HostIp string
Port int
User string
Password string //读
Type string
}
var SSHServerSetting = &SSHServer{}
func SetUp() {
var err error
//加载配置文件
cfg, err = ini.Load("../conf/conf.ini")
if err != nil {
log.Fatalf("setting.Setup, fail to parse 'app/conf/config.ini': %v", err)
}
mapTo("ssh", SSHServerSetting)
fmt.Println("这是init获取到的", SSHServerSetting.HostIp)
}
// mapTo map section
func mapTo(section string, v interface{}) {
err := cfg.Section(section).MapTo(v)
if err != nil {
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
}
}
func GolangSSh() {
//1.读取配置文件,获取到这些属性
sshHost := setting.SSHServerSetting.HostIp
sshUser := setting.SSHServerSetting.User
sshPassword := setting.SSHServerSetting.Password
sshType := setting.SSHServerSetting.Type
sshPort := setting.SSHServerSetting.Port
fmt.Println("这是获取到的配置文件中的主机的名称", sshHost)
//创建sshp登陆配置
config := &ssh.ClientConfig{
Timeout: time.Second, //ssh 连接time out 时间一秒钟, 如果ssh验证错误 会在一秒内返回
User: sshUser,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //这个可以, 但是不够安全
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
}
if sshType == "password" {
config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
}
//dial 获取ssh client
addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
sshClient, err := ssh.Dial("tcp", addr, config)
if err != nil {
log.Fatal("创建ssh client 失败", err)
}
defer sshClient.Close()
//创建ssh-session
session, err := sshClient.NewSession()
if err != nil {
log.Fatal("创建ssh session 失败", err)
}
defer session.Close()
//执行远程命令(需要注意的是通过;分隔命令,不能使用&&)
combo, err := session.CombinedOutput(" cd /; ls -al")
if err != nil {
log.Fatal("远程执行cmd 失败", err)
}
log.Println("命令输出:", string(combo))
}
package main
func init() {
setting.SetUp()
}
func main(){
//调用登录ssh的函数
GolangSSh()
}
查看结果
[root@ecs-431f-0001 cmd]# go run main.go
这是init获取到的 117.78.5.222
这是获取到的配置文件中的主机的名称 117.78.5.222
2021/09/17 17:19:54 命令输出: total 128
dr-xr-xr-x. 29 root root 4096 Sep 14 09:47 .
dr-xr-xr-x. 29 root root 4096 Sep 14 09:47 ..
-rw-r--r-- 1 root root 0 Dec 12 2020 .autorelabel
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
dr-xr-xr-x. 5 root root 4096 Mar 5 2021 boot
drwxr-xr-x 7 root root 4096 Dec 12 2020 CloudResetPwdUpdateAgent
drwxr-xr-x 7 root root 4096 Dec 12 2020 CloudrResetPwdAgent
drwxr-xr-x 9 root root 4096 Jul 4 11:45 cust2
drwxr-xr-x 19 root root 2960 Aug 21 18:41 dev
drwxr-xr-x 3 root root 4096 Jul 8 09:19 docker
drwxr-xr-x. 93 root root 4096 Sep 1 09:42 etc
drwxr-xr-x. 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------. 2 root root 16384 Dec 12 2020 lost+found
drwxr-xr-x. 2 root root 4096 Nov 3 2020 media
drwxr-xr-x. 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 3 root root 4096 Jun 5 13:44 mydata
drwxr-xr-x 3 root root 4096 Aug 2 18:24 nfsdata
-rw-r--r-- 1 root root 5500 Sep 14 09:45 nginx.conf
drwxrwxrwx 2 root root 4096 Sep 15 20:33 nginxvolume
drwxr-xr-x. 11 root root 4096 Aug 27 13:07 opt
drwxr-xr-x 3 root root 4096 Aug 18 13:24 path
dr-xr-xr-x 219 root root 0 Aug 21 18:41 proc
drwxr-xr-x 4 root root 4096 May 9 12:42 qcwork
dr-xr-x---. 11 root root 4096 Sep 17 14:23 root
drwxr-xr-x 28 root root 940 Aug 31 09:27 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 3 root root 4096 Jul 20 17:49 src
drwxr-xr-x. 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Aug 21 18:41 sys
drwxr-xr-x 4 root root 4096 Sep 15 09:19 test
drwxrwxrwt. 175 root root 12288 Sep 17 17:19 tmp
drwxr-xr-x. 13 root root 4096 Mar 3 2021 usr
drwxr-xr-x. 20 root root 4096 Mar 5 2021 var
源码分析:读取配置的过程
//这个函数其实就是将sections和struct对应起来,可以对应多个
mapTo("ssh", SSHServerSetting)
// mapTo map section
func mapTo(section string, v interface{}) {
err := cfg.Section(section).MapTo(v)
if err != nil {
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
}
}
//首先将传过来的参数ssh,去配置文件中寻找
func (f *File) Section(name string) *Section {
sec, err := f.GetSection(name) //找到就返回
if err != nil {
// Note: It's OK here because the only possible error is empty section name,
// but if it's empty, this piece of code won't be executed.
sec, _ = f.NewSection(name) //没有找到就创建一个
return sec
}
return sec
}
//通过传递过来的参数进行创建
func (f *File) NewSection(name string) (*Section, error) {
if len(name) == 0 {
return nil, errors.New("empty section name")
}
if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection {
name = strings.ToLower(name)
}
if f.BlockMode {
f.lock.Lock()
defer f.lock.Unlock()
}
if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) {
return f.sections[name][0], nil
}
f.sectionList = append(f.sectionList, name)
// NOTE: Append to indexes must happen before appending to sections,
// otherwise index will have off-by-one problem.
f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name]))
sec := newSection(f, name)
f.sections[name] = append(f.sections[name], sec)
return sec, nil
}