mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-21 22:36:39 +00:00
Trace all processes in a container.
This commit is contained in:
@@ -46,13 +46,8 @@ def ignore_error(f):
|
||||
|
||||
@app.route('/')
|
||||
def hello():
|
||||
counter_future = pool.submit(do_redis)
|
||||
search_future = pool.submit(do_search)
|
||||
qotd_future = pool.submit(do_qotd)
|
||||
result = 'Hello World! I have been seen %s times.' % ignore_error(counter_future.result)
|
||||
result += ignore_error(search_future.result)
|
||||
result += ignore_error(qotd_future.result)
|
||||
return result
|
||||
qotd_msg = do_qotd()
|
||||
return qotd_msg
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(format='%(asctime)s %(levelname)s %(filename)s:%(lineno)d - %(message)s', level=logging.INFO)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
dockerClient "github.com/fsouza/go-dockerclient"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/probe/process"
|
||||
)
|
||||
|
||||
func respondWith(w http.ResponseWriter, code int, response interface{}) {
|
||||
@@ -23,10 +24,30 @@ func respondWith(w http.ResponseWriter, code int, response interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer) pidsForContainer(id string) ([]int, error) {
|
||||
var container docker.Container
|
||||
t.docker.WalkContainers(func(c docker.Container) {
|
||||
if c.ID() == id {
|
||||
container = c
|
||||
}
|
||||
})
|
||||
|
||||
if container == nil {
|
||||
return []int{}, fmt.Errorf("Not Found")
|
||||
}
|
||||
|
||||
pidTree, err := process.NewTree(process.NewWalker("/proc"))
|
||||
if err != nil {
|
||||
return []int{}, err
|
||||
}
|
||||
|
||||
return pidTree.GetChildren(container.PID())
|
||||
}
|
||||
|
||||
func (t *tracer) http(port int) {
|
||||
router := mux.NewRouter()
|
||||
|
||||
router.Methods("GET").Path("/containers").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
router.Methods("GET").Path("/container").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
containers := []*dockerClient.Container{}
|
||||
t.docker.WalkContainers(func(container docker.Container) {
|
||||
containers = append(containers, container.Container())
|
||||
@@ -35,6 +56,34 @@ func (t *tracer) http(port int) {
|
||||
respondWith(w, http.StatusOK, containers)
|
||||
})
|
||||
|
||||
router.Methods("POST").Path("/container/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
id := mux.Vars(r)["id"]
|
||||
children, err := t.pidsForContainer(id)
|
||||
if err != nil {
|
||||
respondWith(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, pid := range children {
|
||||
t.ptrace.TraceProcess(pid)
|
||||
}
|
||||
w.WriteHeader(204)
|
||||
})
|
||||
|
||||
router.Methods("DELETE").Path("/container/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
id := mux.Vars(r)["id"]
|
||||
children, err := t.pidsForContainer(id)
|
||||
if err != nil {
|
||||
respondWith(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, pid := range children {
|
||||
t.ptrace.StopTracing(pid)
|
||||
}
|
||||
w.WriteHeader(204)
|
||||
})
|
||||
|
||||
router.Methods("GET").Path("/pid").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
respondWith(w, http.StatusOK, t.ptrace.AttachedPIDs())
|
||||
})
|
||||
@@ -61,6 +110,8 @@ func (t *tracer) http(port int) {
|
||||
w.WriteHeader(204)
|
||||
})
|
||||
|
||||
|
||||
|
||||
router.Methods("GET").Path("/traces").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
respondWith(w, http.StatusOK, t.store.Traces())
|
||||
})
|
||||
|
||||
@@ -13,6 +13,7 @@ const (
|
||||
READ = 0
|
||||
WRITE = 1
|
||||
CLOSE = 3
|
||||
STAT = 4
|
||||
MMAP = 9
|
||||
MPROTECT = 10
|
||||
MADVISE = 28
|
||||
@@ -96,7 +97,7 @@ func (t *thread) syscallStopped() {
|
||||
t.handleIO(&t.callRegs, &t.resultRegs)
|
||||
|
||||
// we can ignore these syscalls
|
||||
case SETROBUSTLIST, GETID, MMAP, MPROTECT, MADVISE, SOCKET, CLONE:
|
||||
case SETROBUSTLIST, GETID, MMAP, MPROTECT, MADVISE, SOCKET, CLONE, STAT:
|
||||
return
|
||||
|
||||
default:
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
function updateContainers() {
|
||||
$.get("/containers").done(function (data) {
|
||||
$.get("/container").done(function (data) {
|
||||
data.sort(function (a, b) {
|
||||
if (a.Name > b.Name) {
|
||||
return 1;
|
||||
@@ -99,14 +99,14 @@
|
||||
$("body").on("click", "div.mainview button.start", function() {
|
||||
var id = $(this).parent().data("containerId")
|
||||
var container = containersByID[id]
|
||||
$.post(sprintf("/pid/%d", container.State.Pid))
|
||||
$.post(sprintf("/container/%s", container.Id))
|
||||
})
|
||||
|
||||
$("body").on("click", "div.mainview button.stop", function() {
|
||||
var id = $(this).parent().data("containerId")
|
||||
var container = containersByID[id]
|
||||
$.ajax({
|
||||
url: sprintf("/pid/%d", container.State.Pid),
|
||||
url: sprintf("/container/%s", container.Id),
|
||||
type: 'DELETE',
|
||||
});
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
// Tree represents all processes on the machine.
|
||||
type Tree interface {
|
||||
GetParent(pid int) (int, error)
|
||||
GetChildren(pid int) ([]int, error)
|
||||
}
|
||||
|
||||
type tree struct {
|
||||
@@ -32,3 +33,30 @@ func (pt *tree) GetParent(pid int) (int, error) {
|
||||
|
||||
return proc.PPID, nil
|
||||
}
|
||||
|
||||
// GetChildren
|
||||
func (pt *tree) GetChildren(pid int) ([]int, error) {
|
||||
_, ok := pt.processes[pid]
|
||||
if !ok {
|
||||
return []int{}, fmt.Errorf("PID %d not found", pid)
|
||||
}
|
||||
|
||||
var isChild func(id int) bool
|
||||
isChild = func(id int) bool {
|
||||
p, ok := pt.processes[id]
|
||||
if !ok || p.PPID == 0 {
|
||||
return false
|
||||
} else if p.PPID == pid {
|
||||
return true
|
||||
}
|
||||
return isChild(p.PPID)
|
||||
}
|
||||
|
||||
children := []int{pid}
|
||||
for id, _ := range pt.processes {
|
||||
if isChild(id) {
|
||||
children = append(children, id)
|
||||
}
|
||||
}
|
||||
return children, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user