ing
This commit is contained in:
parent
1076082050
commit
1552f4eaba
96
crawler/crawler.go
Normal file
96
crawler/crawler.go
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
package crawler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/ssh_crawler/ssh"
|
||||||
|
"git.loafle.net/overflow/ssh_crawler/stat"
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Crawler struct {
|
||||||
|
sshCli *ssh.SSHClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ip, port, user, pw string) (*Crawler, error) {
|
||||||
|
c := &Crawler{}
|
||||||
|
err := c.connectSSH(ip, port, user, pw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crawler) connectSSH(ip, port, user, pw string) error {
|
||||||
|
client, err := ssh.New(ip, port, user, pw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.sshCli = client
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (c *Crawler) CPUStat()([]stat.CPUStat, error) {
|
||||||
|
cpu := &stat.CPUStat{}
|
||||||
|
|
||||||
|
b, err := c.sshCli.RunCommand(cpu.Command())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.Parse(bytes.NewReader(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crawler) MEMStat()(map[string]string, error) {
|
||||||
|
mem := &stat.MEMStat{}
|
||||||
|
|
||||||
|
b, err := c.sshCli.RunCommand(mem.Command())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem.Parse(bytes.NewReader(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crawler) DiskIOStat()([]stat.DiskIOStat, error) {
|
||||||
|
diskio := &stat.DiskIOStat{}
|
||||||
|
|
||||||
|
b, err := c.sshCli.RunCommand(diskio.Command())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return diskio.Parse(bytes.NewReader(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crawler) DiskFreeStat()([]stat.DiskFreeStat, error) {
|
||||||
|
diskFree := &stat.DiskFreeStat{}
|
||||||
|
|
||||||
|
b, err := c.sshCli.RunCommand(diskFree.Command())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return diskFree.Parse(bytes.NewReader(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crawler) LoadAvgStat()(stat.LoadAvg, error) {
|
||||||
|
load := &stat.LoadAvg{}
|
||||||
|
|
||||||
|
b, err := c.sshCli.RunCommand(load.Command())
|
||||||
|
if err != nil {
|
||||||
|
return stat.LoadAvg{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return load.Parse(bytes.NewReader(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crawler) NetworkStat() ([]stat.NetDevStat, error) {
|
||||||
|
net := &stat.NetDevStat{}
|
||||||
|
b, err := c.sshCli.RunCommand(net.Command())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.Parse(bytes.NewReader(b))
|
||||||
|
}
|
53
main.go
53
main.go
|
@ -1,8 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.loafle.net/overflow/ssh_crawler/ssh"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/ssh_crawler/crawler"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,29 +13,56 @@ func main() {
|
||||||
const user = "administrator"
|
const user = "administrator"
|
||||||
const pw = "!@#$qwer1234"
|
const pw = "!@#$qwer1234"
|
||||||
|
|
||||||
client, err := connectSSH(ip, port, user, pw)
|
cr, err := crawler.New(ip, port, user, pw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("%s", err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := client.CPUStat()
|
//CPU
|
||||||
|
cpu, err := cr.CPUStat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("%s", err)
|
fmt.Printf("err : %s\n", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("%s", res)
|
fmt.Printf("CPU: %s\n", cpu)
|
||||||
|
|
||||||
client.Close()
|
//MEM
|
||||||
}
|
mem, err := cr.MEMStat()
|
||||||
|
|
||||||
func connectSSH(ip, port, user, pw string) (*ssh.SSHClient, error){
|
|
||||||
client, err := ssh.New(ip, port, user, pw)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
fmt.Printf("err : %s\n", err)
|
||||||
}
|
}
|
||||||
return client, nil
|
fmt.Printf("MEM: %s\n", mem)
|
||||||
|
|
||||||
|
//Disk IO
|
||||||
|
diskio, err := cr.DiskIOStat()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err : %s\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("DiskIO: %s\n", diskio)
|
||||||
|
|
||||||
|
//Disk Free
|
||||||
|
diskFree, err := cr.DiskFreeStat()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err : %s\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("DiskFree: %s\n", diskFree)
|
||||||
|
|
||||||
|
//Load Avg.
|
||||||
|
load, err := cr.LoadAvgStat()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err : %s\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Load: %s\n", load)
|
||||||
|
|
||||||
|
//Network
|
||||||
|
net, err := cr.NetworkStat()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err : %s\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Net: %s\n", net)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
58
ssh/ssh.go
58
ssh/ssh.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"bytes"
|
"bytes"
|
||||||
"git.loafle.net/overflow/ssh_crawler/stat"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,12 +15,13 @@ type SSHConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SSHClient struct {
|
type SSHClient struct {
|
||||||
Session *ssh.Session
|
session *ssh.Session
|
||||||
|
conf *SSHConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ip, port, user, pw string) (*SSHClient, error) {
|
func New(ip, port, user, pw string) (*SSHClient, error) {
|
||||||
p, _ := strconv.Atoi(port)
|
p, _ := strconv.Atoi(port)
|
||||||
info := &SSHConfig {
|
conf := &SSHConfig {
|
||||||
User: user,
|
User: user,
|
||||||
Auth: []ssh.AuthMethod{
|
Auth: []ssh.AuthMethod{
|
||||||
ssh.Password(pw),
|
ssh.Password(pw),
|
||||||
|
@ -29,31 +29,24 @@ func New(ip, port, user, pw string) (*SSHClient, error) {
|
||||||
Host: ip,
|
Host: ip,
|
||||||
Port: p,
|
Port: p,
|
||||||
}
|
}
|
||||||
session, err := info.Session()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Errorf("%s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SSHClient{
|
return &SSHClient{conf:conf}, nil
|
||||||
Session: session,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (info *SSHConfig) Session() (*ssh.Session, error) {
|
func (cli *SSHClient) Session() error {
|
||||||
sshConfig := &ssh.ClientConfig{
|
sshConfig := &ssh.ClientConfig{
|
||||||
User: info.User,
|
User: cli.conf.User,
|
||||||
Auth: info.Auth,
|
Auth: cli.conf.Auth,
|
||||||
HostKeyCallback:ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback:ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
connection, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", info.Host, info.Port), sshConfig)
|
connection, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", cli.conf.Host, cli.conf.Port), sshConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
session, err := connection.NewSession()
|
session, err := connection.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
modes := ssh.TerminalModes{
|
modes := ssh.TerminalModes{
|
||||||
|
@ -64,37 +57,30 @@ func (info *SSHConfig) Session() (*ssh.Session, error) {
|
||||||
|
|
||||||
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
|
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
|
||||||
session.Close()
|
session.Close()
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cli.session = session
|
||||||
|
|
||||||
return session, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *SSHClient) Close() {
|
|
||||||
cli.Session.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cli *SSHClient) RunCommand(command string) ([]byte, error) {
|
func (cli *SSHClient) RunCommand(command string) ([]byte, error) {
|
||||||
|
|
||||||
var b bytes.Buffer
|
if err := cli.Session(); err != nil {
|
||||||
cli.Session.Stdout = &b
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
err := cli.Session.Run(command)
|
var b bytes.Buffer
|
||||||
|
cli.session.Stdout = &b
|
||||||
|
|
||||||
|
err := cli.session.Run(command)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cli.session.Close()
|
||||||
|
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *SSHClient) CPUStat()([]stat.CPUStat, error) {
|
|
||||||
cpu := &stat.CPUStat{}
|
|
||||||
|
|
||||||
b, err := cli.RunCommand(cpu.Command())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cpu.Parse(bytes.NewReader(b))
|
|
||||||
}
|
|
||||||
|
|
49
stat/disk_free.go
Normal file
49
stat/disk_free.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package stat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiskFreeStat struct {
|
||||||
|
filesystem,
|
||||||
|
size,
|
||||||
|
used,
|
||||||
|
available,
|
||||||
|
usePerc,
|
||||||
|
mountedOn string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (diskFree DiskFreeStat) Command() string {
|
||||||
|
return "df -k"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (diskio DiskFreeStat) Parse(r io.Reader) ([]DiskFreeStat, error) {
|
||||||
|
|
||||||
|
var scanner = bufio.NewScanner(r)
|
||||||
|
var stats = []DiskFreeStat{}
|
||||||
|
|
||||||
|
scanner.Scan()
|
||||||
|
for scanner.Scan() {
|
||||||
|
parts := strings.Fields(scanner.Text())
|
||||||
|
stats = append(stats, DiskFreeStat{
|
||||||
|
filesystem: parts[0],
|
||||||
|
size: parts[1],
|
||||||
|
used: parts[2],
|
||||||
|
available: parts[3],
|
||||||
|
usePerc: removePercUnit(parts[4]),
|
||||||
|
mountedOn: parts[5],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, scanner.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePercUnit(str string) string {
|
||||||
|
if !strings.HasSuffix(str, "%"){
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
str = str[:len(str)-1]
|
||||||
|
return str
|
||||||
|
}
|
62
stat/disk_io.go
Normal file
62
stat/disk_io.go
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
package stat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiskIOStat struct {
|
||||||
|
device,
|
||||||
|
readCompleted,
|
||||||
|
readMerged,
|
||||||
|
sectorRead,
|
||||||
|
timeSpentReading,
|
||||||
|
writesCompleted,
|
||||||
|
writesMerged,
|
||||||
|
sectorsWritten,
|
||||||
|
timeSpentWriting,
|
||||||
|
ioInProg,
|
||||||
|
timeSpentIO,
|
||||||
|
weightedTimeSpentIO string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (diskio DiskIOStat) Command() string {
|
||||||
|
return "cat /proc/diskstats"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (diskio DiskIOStat) Parse(r io.Reader) ([]DiskIOStat, error) {
|
||||||
|
var (
|
||||||
|
DiskIOStats = []DiskIOStat{}
|
||||||
|
scanner = bufio.NewScanner(r)
|
||||||
|
)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
parts := strings.Fields(scanner.Text())
|
||||||
|
if len(parts) < 4 {
|
||||||
|
return nil, fmt.Errorf("invalid line in %s: %s", "/proc/diskstats", scanner.Text())
|
||||||
|
}
|
||||||
|
deviceName := parts[2]
|
||||||
|
if !strings.HasPrefix(deviceName, "sd") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
DiskIOStats = append(DiskIOStats, DiskIOStat{
|
||||||
|
device: deviceName,
|
||||||
|
readCompleted: parts[3],
|
||||||
|
readMerged: parts[4],
|
||||||
|
sectorRead: parts[5],
|
||||||
|
timeSpentReading: parts[6],
|
||||||
|
writesCompleted: parts[7],
|
||||||
|
writesMerged: parts[8],
|
||||||
|
sectorsWritten: parts[9],
|
||||||
|
timeSpentWriting: parts[10],
|
||||||
|
ioInProg: parts[11],
|
||||||
|
timeSpentIO: parts[12],
|
||||||
|
weightedTimeSpentIO: parts[13],
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return DiskIOStats, scanner.Err()
|
||||||
|
}
|
33
stat/loadavg.go
Normal file
33
stat/loadavg.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package stat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoadAvg struct {
|
||||||
|
min1,
|
||||||
|
min5,
|
||||||
|
min15 string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (loadavg LoadAvg) Command() string {
|
||||||
|
return "cat /proc/loadavg"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (loadavg LoadAvg) Parse(r io.Reader) (LoadAvg, error) {
|
||||||
|
var (
|
||||||
|
scanner = bufio.NewScanner(r)
|
||||||
|
)
|
||||||
|
|
||||||
|
load := LoadAvg{}
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
load.min1 = parts[0]
|
||||||
|
load.min5 = parts[1]
|
||||||
|
load.min15 = parts[2]
|
||||||
|
}
|
||||||
|
return load, scanner.Err()
|
||||||
|
}
|
31
stat/mem.go
Normal file
31
stat/mem.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package stat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"bufio"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MEMStat struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cpu MEMStat) Command() string {
|
||||||
|
return "cat /proc/meminfo"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cpu MEMStat) Parse(r io.Reader) (map[string]string, error) {
|
||||||
|
var (
|
||||||
|
memInfo = map[string]string{}
|
||||||
|
scanner = bufio.NewScanner(r)
|
||||||
|
)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
key := parts[0][:len(parts[0])-1]
|
||||||
|
memInfo[key] = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return memInfo, scanner.Err()
|
||||||
|
}
|
79
stat/network.go
Normal file
79
stat/network.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package stat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"bufio"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NetDevStat struct {
|
||||||
|
iface,
|
||||||
|
recvByte,
|
||||||
|
recvPacket,
|
||||||
|
recvErr,
|
||||||
|
recvDrop,
|
||||||
|
recvFifo,
|
||||||
|
recvFrame,
|
||||||
|
recvCompressed,
|
||||||
|
recvMulticast,
|
||||||
|
transByte,
|
||||||
|
transPacket,
|
||||||
|
transErr,
|
||||||
|
transDrop,
|
||||||
|
transFifo,
|
||||||
|
transFrame,
|
||||||
|
transCompressed,
|
||||||
|
transMulticast string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *NetDevStat) Command() string {
|
||||||
|
return "cat /proc/net/dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *NetDevStat) Parse(r io.Reader) ([]NetDevStat, error) {
|
||||||
|
var (
|
||||||
|
scanner = bufio.NewScanner(r)
|
||||||
|
procNetDevFieldSep = regexp.MustCompile("[ :] *")
|
||||||
|
netDevStats = []NetDevStat{}
|
||||||
|
)
|
||||||
|
scanner.Scan()
|
||||||
|
scanner.Scan()
|
||||||
|
parts := strings.Split(scanner.Text(), "|")
|
||||||
|
if len(parts) != 3 { // interface + receive + transmit
|
||||||
|
return nil, fmt.Errorf("invalid header line in net/dev: %s",
|
||||||
|
scanner.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
header := strings.Fields(parts[1])
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimLeft(scanner.Text(), " ")
|
||||||
|
parts := procNetDevFieldSep.Split(line, -1)
|
||||||
|
if len(parts) != 2*len(header)+1 {
|
||||||
|
return nil, fmt.Errorf("invalid line in net/dev: %s", scanner.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
dev := parts[0][:len(parts[0])]
|
||||||
|
netDevStats = append(netDevStats, NetDevStat{
|
||||||
|
iface: dev,
|
||||||
|
recvByte: parts[1],
|
||||||
|
recvPacket: parts[2],
|
||||||
|
recvErr: parts[3],
|
||||||
|
recvDrop: parts[4],
|
||||||
|
recvFifo: parts[5],
|
||||||
|
recvFrame: parts[6],
|
||||||
|
recvCompressed: parts[7],
|
||||||
|
recvMulticast: parts[8],
|
||||||
|
transByte: parts[9],
|
||||||
|
transPacket: parts[10],
|
||||||
|
transErr: parts[11],
|
||||||
|
transDrop: parts[12],
|
||||||
|
transFifo: parts[13],
|
||||||
|
transFrame: parts[14],
|
||||||
|
transCompressed: parts[15],
|
||||||
|
transMulticast: parts[16],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return netDevStats, scanner.Err()
|
||||||
|
}
|
|
@ -4,5 +4,5 @@ import "io"
|
||||||
|
|
||||||
type Stat interface {
|
type Stat interface {
|
||||||
Command() string
|
Command() string
|
||||||
Parse(r io.Reader) ([]CPUStat, error)
|
Parse(r io.Reader) (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user