From 1552f4eaba03d3c8fa27d1fc507021fc820ca3d3 Mon Sep 17 00:00:00 2001 From: insanity Date: Mon, 23 Oct 2017 14:31:04 +0900 Subject: [PATCH] ing --- crawler/crawler.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++ main.go | 53 ++++++++++++++++++------- ssh/ssh.go | 58 +++++++++++----------------- stat/disk_free.go | 49 +++++++++++++++++++++++ stat/disk_io.go | 62 ++++++++++++++++++++++++++++++ stat/loadavg.go | 33 ++++++++++++++++ stat/mem.go | 31 +++++++++++++++ stat/network.go | 79 ++++++++++++++++++++++++++++++++++++++ stat/stat.go | 2 +- 9 files changed, 413 insertions(+), 50 deletions(-) create mode 100644 crawler/crawler.go create mode 100644 stat/disk_free.go create mode 100644 stat/disk_io.go create mode 100644 stat/loadavg.go create mode 100644 stat/mem.go create mode 100644 stat/network.go diff --git a/crawler/crawler.go b/crawler/crawler.go new file mode 100644 index 0000000..43e09b8 --- /dev/null +++ b/crawler/crawler.go @@ -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)) +} \ No newline at end of file diff --git a/main.go b/main.go index e104bc8..e1dde98 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,8 @@ package main import ( - "git.loafle.net/overflow/ssh_crawler/ssh" "fmt" + "git.loafle.net/overflow/ssh_crawler/crawler" ) @@ -13,29 +13,56 @@ func main() { const user = "administrator" const pw = "!@#$qwer1234" - client, err := connectSSH(ip, port, user, pw) + cr, err := crawler.New(ip, port, user, pw) if err != nil { - fmt.Errorf("%s", err) + fmt.Println(err) } - res, err := client.CPUStat() + //CPU + cpu, err := cr.CPUStat() 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() -} - -func connectSSH(ip, port, user, pw string) (*ssh.SSHClient, error){ - client, err := ssh.New(ip, port, user, pw) + //MEM + mem, err := cr.MEMStat() 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) } + diff --git a/ssh/ssh.go b/ssh/ssh.go index 80489da..d47fe28 100644 --- a/ssh/ssh.go +++ b/ssh/ssh.go @@ -4,7 +4,6 @@ import ( "fmt" "golang.org/x/crypto/ssh" "bytes" - "git.loafle.net/overflow/ssh_crawler/stat" "strconv" ) @@ -16,12 +15,13 @@ type SSHConfig struct { } type SSHClient struct { - Session *ssh.Session + session *ssh.Session + conf *SSHConfig } func New(ip, port, user, pw string) (*SSHClient, error) { p, _ := strconv.Atoi(port) - info := &SSHConfig { + conf := &SSHConfig { User: user, Auth: []ssh.AuthMethod{ ssh.Password(pw), @@ -29,31 +29,24 @@ func New(ip, port, user, pw string) (*SSHClient, error) { Host: ip, Port: p, } - session, err := info.Session() - if err != nil { - fmt.Errorf("%s", err) - return nil, err - } - return &SSHClient{ - Session: session, - }, nil + return &SSHClient{conf:conf}, nil } -func (info *SSHConfig) Session() (*ssh.Session, error) { +func (cli *SSHClient) Session() error { sshConfig := &ssh.ClientConfig{ - User: info.User, - Auth: info.Auth, + User: cli.conf.User, + Auth: cli.conf.Auth, 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 { - return nil, err + return err } session, err := connection.NewSession() if err != nil { - return nil, err + return err } modes := ssh.TerminalModes{ @@ -64,37 +57,30 @@ func (info *SSHConfig) Session() (*ssh.Session, error) { if err := session.RequestPty("xterm", 80, 40, modes); err != nil { 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) { - var b bytes.Buffer - cli.Session.Stdout = &b + if err := cli.Session(); err != nil { + return nil, err + } - err := cli.Session.Run(command) + var b bytes.Buffer + cli.session.Stdout = &b + + err := cli.session.Run(command) if err != nil { return nil, err } + cli.session.Close() + 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)) -} diff --git a/stat/disk_free.go b/stat/disk_free.go new file mode 100644 index 0000000..1159daf --- /dev/null +++ b/stat/disk_free.go @@ -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 +} \ No newline at end of file diff --git a/stat/disk_io.go b/stat/disk_io.go new file mode 100644 index 0000000..2ec8c51 --- /dev/null +++ b/stat/disk_io.go @@ -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() +} \ No newline at end of file diff --git a/stat/loadavg.go b/stat/loadavg.go new file mode 100644 index 0000000..f0c3972 --- /dev/null +++ b/stat/loadavg.go @@ -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() +} diff --git a/stat/mem.go b/stat/mem.go new file mode 100644 index 0000000..31bc4ce --- /dev/null +++ b/stat/mem.go @@ -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() +} diff --git a/stat/network.go b/stat/network.go new file mode 100644 index 0000000..2c4ea56 --- /dev/null +++ b/stat/network.go @@ -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() +} \ No newline at end of file diff --git a/stat/stat.go b/stat/stat.go index 8bdd152..4eeb45b 100644 --- a/stat/stat.go +++ b/stat/stat.go @@ -4,5 +4,5 @@ import "io" type Stat interface { Command() string - Parse(r io.Reader) ([]CPUStat, error) + Parse(r io.Reader) (interface{}, error) }