1
0
mirror of https://github.com/google/gops.git synced 2024-11-24 08:22:25 +02:00
gops/main.go

119 lines
2.6 KiB
Go
Raw Normal View History

2016-11-04 07:43:04 +02:00
// Copyright 2016 The Go Authors. All rights reserved.
2016-11-04 01:56:19 +02:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Program gops is a tool to list currently running Go processes.
2016-11-03 23:01:55 +02:00
package main
import (
"bytes"
2016-11-03 23:01:55 +02:00
"fmt"
2016-11-04 07:32:46 +02:00
"os"
"strconv"
"strings"
2016-11-03 23:01:55 +02:00
"github.com/google/gops/goprocess"
2016-11-03 23:01:55 +02:00
)
2016-11-04 07:32:46 +02:00
const helpText = `Usage: gops is a tool to list and diagnose Go processes.
2016-11-04 08:05:56 +02:00
2016-11-04 07:32:46 +02:00
2016-11-14 07:59:09 +02:00
Commands:
stack Prints the stack trace.
2017-01-20 04:50:59 +02:00
gc Runs the garbage collector and blocks until successful.
memstats Prints the allocation and garbage collection stats.
2016-11-14 07:59:09 +02:00
version Prints the Go version used to build the program.
2017-01-03 11:15:13 +02:00
stats Prints the vital runtime stats.
2017-01-20 04:50:59 +02:00
help Prints this help text.
2016-11-14 07:59:09 +02:00
2017-01-20 04:50:59 +02:00
Profiling commands:
2017-01-20 23:09:45 +02:00
trace Runs the runtime tracer for 5 secs and launches "go tool trace".
2016-11-14 07:59:09 +02:00
pprof-heap Reads the heap profile and launches "go tool pprof".
2016-11-20 23:16:04 +02:00
pprof-cpu Reads the CPU profile and launches "go tool pprof".
2016-11-14 07:59:09 +02:00
2016-11-04 08:05:56 +02:00
2016-11-08 03:29:14 +02:00
All commands require the agent running on the Go process.
Symbol "*" indicates the process runs the agent.`
2016-11-04 07:32:46 +02:00
2016-11-04 08:05:56 +02:00
// TODO(jbd): add link that explains the use of agent.
2016-11-03 23:01:55 +02:00
func main() {
2016-11-04 07:32:46 +02:00
if len(os.Args) < 2 {
2016-11-08 03:29:14 +02:00
processes()
2016-11-04 07:32:46 +02:00
return
}
2016-11-08 03:29:14 +02:00
cmd := os.Args[1]
2016-11-12 05:55:16 +02:00
if cmd == "help" {
usage("")
}
2017-01-02 05:54:15 +02:00
if len(os.Args) < 3 {
2017-03-02 21:51:14 +02:00
usage("missing PID or address")
2017-01-02 05:54:15 +02:00
}
2016-11-08 03:29:14 +02:00
fn, ok := cmds[cmd]
if !ok {
usage("unknown subcommand")
2016-11-04 07:32:46 +02:00
}
2017-03-02 21:51:14 +02:00
addr, err := targetToAddr(os.Args[2])
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't resolve addr or pid %v to TCPAddress: %v\n", os.Args[2], err)
os.Exit(1)
}
if err := fn(*addr); err != nil {
2016-11-08 03:29:14 +02:00
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
2016-11-04 07:32:46 +02:00
}
}
2016-11-08 03:29:14 +02:00
func processes() {
ps := goprocess.Find()
var maxPID, maxExec, maxVersion int
for _, p := range ps {
maxPID = max(maxPID, len(strconv.Itoa(p.PID)))
maxExec = max(maxExec, len(p.Exec))
maxVersion = max(maxVersion, len(p.BuildVersion))
}
for _, p := range ps {
buf := bytes.NewBuffer(nil)
pid := strconv.Itoa(p.PID)
fmt.Fprint(buf, pad(pid, maxPID))
if p.Agent {
fmt.Fprint(buf, "*")
} else {
fmt.Fprint(buf, " ")
}
fmt.Fprint(buf, " ")
fmt.Fprint(buf, pad(p.Exec, maxExec))
fmt.Fprint(buf, " ")
fmt.Fprint(buf, pad(p.BuildVersion, maxVersion))
fmt.Fprint(buf, " ")
fmt.Fprint(buf, p.Path)
fmt.Fprintln(buf)
buf.WriteTo(os.Stdout)
}
2016-11-03 23:01:55 +02:00
}
2016-11-04 07:32:46 +02:00
2016-11-08 03:29:14 +02:00
func usage(msg string) {
if msg != "" {
fmt.Printf("gops: %v\n", msg)
2016-11-04 07:32:46 +02:00
}
2016-11-08 03:29:14 +02:00
fmt.Fprintf(os.Stderr, "%v\n", helpText)
2016-11-04 09:55:16 +02:00
os.Exit(1)
2016-11-04 07:32:46 +02:00
}
func pad(s string, total int) string {
if len(s) >= total {
return s
}
return s + strings.Repeat(" ", total-len(s))
}
func max(i, j int) int {
if i > j {
return i
}
return j
}