前言
这是一个轮子。
大家都知道 Ansible 是功能超级强大的自动化运维工具,十分的高大上。太高大上了以至于在低端运维有点水土不服,在于三点:
-
Ansible 是基于 Python 的,而 Python 下的安装是有一堆依赖的。。。不要笑!对于很多使用 Win 的用户而言,光是装 Python, 装 pip 就够喝一壶的了。
Ansible 的 paybook 所使用的 yaml 语法当然非常强大了。然而对于新人而言,刚入手是玩不转的,需要学习。虽然 Ansible 相比其他的自动化运维工具,它的学习曲线已经非常平易近人了,但毕竟还是要学一下的不是么
Ansible 自动化运维 Linux 服务器得益于 Linux 上 python 的默认支持,功能非常强大。然而如果拿来跑交换机的话,因为交换机上通常没有 python 环境,功能就要打很多折扣了。基本上也就是执行一系列的命令组合。而我们这种有大片园区网的传统单位,运维的大头正式是交换机~
所以造这个轮子的出发点是基于以下考虑的:
-
要跨平台,木有依赖,开箱即用。用 Go 来撸一个就能很好的满足这个需求。你看 Open-Falcon 的 agent,ELK 的 beats ,都选择用 Go 来实现,就是这个原因。
简单无脑,无需学习。直接堆砌命令行就行,就像我们初始化交换机的那种命令行组合模板。只要 cli 会玩,直接照搬过来就行。
要支持并发。这个是 Go 的强项了,无需多言。
最后当然是学习 Go 啦。
一点都没有黑 Ansible 的意思。我们也有在用 Ansible 来做自动化运维的工作,我觉得所有运维最好都学习下 Ansible,将来总是要往自动化的方向走的。这个轮子的目的在于学习 Ansible 之前,先有个够简单无脑的工具解决下眼前的需求~
建立 ssh 会话
Go 自身不带 ssh 包。他的 ssh 包放在了 https://godoc.org/golang.org/x/crypto/ssh 这里。import 他就好
import "golang.org/x/crypto/ssh"
首先我们需要建立一个 ssh 会话,比如这样。
func connect(user, password, host, key string, port int, cipherList []string) (*ssh.Session, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
client *ssh.Client
config ssh.Config
session *ssh.Session
err error
)
// get auth method
auth = make([]ssh.AuthMethod, 0)
if key == "" {
auth = append(auth, ssh.Password(password))
} else {
pemBytes, err := ioutil.ReadFile(key)
if err != nil {
return nil, err
}
var signer ssh.Signer
if password == "" {
signer, err = ssh.ParsePrivateKey(pemBytes)
} else {
signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password))
}
if err != nil {
return nil, err
}
auth = append(auth, ssh.PublicKeys(signer))
}
if len(cipherList) == 0 {
config = ssh.Config{
Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"},
}
} else {
config = ssh.Config{
Ciphers: cipherList,
}
}
clientConfig = &ssh.ClientConfig{
User: user,
Auth: auth,
Timeout: 30 * time.Second,
Config: config,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
}
// connet to ssh
addr = fmt.Sprintf("%s:%d", host, port)
if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
return nil, err
}
// create session
if session, err = client.NewSession(); err != nil {
return nil, err
}
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
return nil, err
}
return session, nil
}









