Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
freedomkk-qfeng committed Jun 7, 2017
0 parents commit 9e410ea
Show file tree
Hide file tree
Showing 6 changed files with 545 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.txt
*.json
*.exe
104 changes: 104 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
## multissh

一个简单的并行 SSH 工具,可以批量的对主机通过 SSH 执行命令组合。

#### 编译
```
go get ./...
go build
```


#### 命令体系
```
./multissh -h
-cmd string
cmds // 需要执行的命令组合,多条命令以 ; 分割
-cmdfile string
cmdfile path //需要执行的命令组合文件,文件内命令按行分割
-hostfile string
hostfile path // 需要执行的主机列表文件,主机列表在文件内按行分割
-hosts string
host address list //需要执行的主机列表,多个主机以 ; 分割
-ipfile string
hostfile path //需要执行的主机(IP)列表文件,IP可以以地址段的方式逐行写在文本内
-p string
password // 主机的 SSH 密码
-port int
ssh port (default 22) //主机的 SSH 端口,默认 22
-u string
username //主机的 SSH 用户名
```
**cmdfile 示例**
```
show clock
exit
```
**hostfile 示例**
```
10.10.15.101
10.10.15.102
```
**ipfile 示例**
```
10.10.15.101-10.10.15.102
```

## 用法
#### cmd string & host string
```
./multissh -cmd "show clock;exit" -hosts "10.10.15.101;10.10.15.102" -u admin -p admin
10.10.15.101 ssh start
sw-1#show clock
05:26:40.649 UTC Tue Jun 6 2017
sw-1#exit
10.10.15.101 ssh end
10.10.15.102 ssh start
sw-2#show clock
05:24:38.708 UTC Tue Jun 6 2017
sw-2#exit
10.10.15.102 ssh end
```

#### cmdfile & hostfile
```
./multissh -cmdfile cmd.txt -hostfile host.txt -u admin -p admin
10.10.15.101 ssh start
sw-1#show clock
05:29:43.269 UTC Tue Jun 6 2017
sw-1#exit
10.10.15.101 ssh end
10.10.15.102 ssh start
sw-2#show clock
05:27:41.332 UTC Tue Jun 6 2017
sw-2#exit
10.10.15.102 ssh end
```

#### ipfile
```
./multissh -cmdfile cmd.txt -ipfile ip.txt -u admin -p admin
10.10.15.101 ssh start
sw-1#show clock
05:29:43.269 UTC Tue Jun 6 2017
sw-1#exit
10.10.15.101 ssh end
10.10.15.102 ssh start
sw-2#show clock
05:27:41.332 UTC Tue Jun 6 2017
sw-2#exit
10.10.15.102 ssh end
```

185 changes: 185 additions & 0 deletions cfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package main

import (
"encoding/binary"
"io/ioutil"
"log"
"net"
"strconv"
"strings"
)

func GetfileAll(filePath string) ([]byte, error) {
result, err := ioutil.ReadFile(filePath)
if err != nil {
log.Println("read file ", filePath, err)
return result, err
}
return result, nil
}

func Getfile(filePath string) ([]string, error) {
result := []string{}
b, err := ioutil.ReadFile(filePath)
if err != nil {
log.Println("read file ", filePath, err)
return result, err
}
s := string(b)
for _, lineStr := range strings.Split(s, "\n") {
lineStr = strings.TrimSpace(lineStr)
if lineStr == "" {
continue
}
result = append(result, lineStr)
}
return result, nil
}

func GetIpList(filePath string) ([]string, error) {
res, err := Getfile(filePath)
if err != nil {
return nil, nil
}
var allIp []string
if len(res) > 0 {
for _, sip := range res {
aip := ParseIp(sip)
for _, ip := range aip {
allIp = append(allIp, ip)
}
}
}
return allIp, nil
}

func ParseIp(ip string) []string {
var availableIPs []string
// if ip is "1.1.1.1/",trim /
ip = strings.TrimRight(ip, "/")
if strings.Contains(ip, "/") == true {
if strings.Contains(ip, "/32") == true {
aip := strings.Replace(ip, "/32", "", -1)
availableIPs = append(availableIPs, aip)
} else {
availableIPs = GetAvailableIP(ip)
}
} else if strings.Contains(ip, "-") == true {
ipRange := strings.SplitN(ip, "-", 2)
availableIPs = GetAvailableIPRange(ipRange[0], ipRange[1])
} else {
availableIPs = append(availableIPs, ip)
}
return availableIPs
}

func GetAvailableIPRange(ipStart, ipEnd string) []string {
var availableIPs []string

firstIP := net.ParseIP(ipStart)
endIP := net.ParseIP(ipEnd)
if firstIP.To4() == nil || endIP.To4() == nil {
return availableIPs
}
firstIPNum := ipToInt(firstIP.To4())
EndIPNum := ipToInt(endIP.To4())
pos := int32(1)

newNum := firstIPNum

for newNum <= EndIPNum {
availableIPs = append(availableIPs, intToIP(newNum).String())
newNum = newNum + pos
}
return availableIPs
}

func GetAvailableIP(ipAndMask string) []string {
var availableIPs []string

ipAndMask = strings.TrimSpace(ipAndMask)
ipAndMask = IPAddressToCIDR(ipAndMask)
_, ipnet, _ := net.ParseCIDR(ipAndMask)

firstIP, _ := networkRange(ipnet)
ipNum := ipToInt(firstIP)
size := networkSize(ipnet.Mask)
pos := int32(1)
max := size - 2 // -1 for the broadcast address, -1 for the gateway address

var newNum int32
for attempt := int32(0); attempt < max; attempt++ {
newNum = ipNum + pos
pos = pos%max + 1
availableIPs = append(availableIPs, intToIP(newNum).String())
}
return availableIPs
}

func IPAddressToCIDR(ipAdress string) string {
if strings.Contains(ipAdress, "/") == true {
ipAndMask := strings.Split(ipAdress, "/")
ip := ipAndMask[0]
mask := ipAndMask[1]
if strings.Contains(mask, ".") == true {
mask = IPMaskStringToCIDR(mask)
}
return ip + "/" + mask
} else {
return ipAdress
}
}

func IPMaskStringToCIDR(netmask string) string {
netmaskList := strings.Split(netmask, ".")
var mint []int
for _, v := range netmaskList {
strv, _ := strconv.Atoi(v)
mint = append(mint, strv)
}
myIPMask := net.IPv4Mask(byte(mint[0]), byte(mint[1]), byte(mint[2]), byte(mint[3]))
ones, _ := myIPMask.Size()
return strconv.Itoa(ones)
}

func IPMaskCIDRToString(one string) string {
oneInt, _ := strconv.Atoi(one)
mIPmask := net.CIDRMask(oneInt, 32)
var maskstring []string
for _, v := range mIPmask {
maskstring = append(maskstring, strconv.Itoa(int(v)))
}
return strings.Join(maskstring, ".")
}

// Calculates the first and last IP addresses in an IPNet
func networkRange(network *net.IPNet) (net.IP, net.IP) {
netIP := network.IP.To4()
firstIP := netIP.Mask(network.Mask)
lastIP := net.IPv4(0, 0, 0, 0).To4()
for i := 0; i < len(lastIP); i++ {
lastIP[i] = netIP[i] | ^network.Mask[i]
}
return firstIP, lastIP
}

// Given a netmask, calculates the number of available hosts
func networkSize(mask net.IPMask) int32 {
m := net.IPv4Mask(0, 0, 0, 0)
for i := 0; i < net.IPv4len; i++ {
m[i] = ^mask[i]
}
return int32(binary.BigEndian.Uint32(m)) + 1
}

// Converts a 4 bytes IP into a 32 bit integer
func ipToInt(ip net.IP) int32 {
return int32(binary.BigEndian.Uint32(ip.To4()))
}

// Converts 32 bit integer into a 4 bytes IP address
func intToIP(n int32) net.IP {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, uint32(n))
return net.IP(b)
}
Loading

0 comments on commit 9e410ea

Please sign in to comment.