123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- package cgroups
- import (
- "bufio"
- "fmt"
- "github.com/dotcloud/docker/mount"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "strconv"
- "strings"
- )
- // https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
- func FindCgroupMountpoint(subsystem string) (string, error) {
- mounts, err := mount.GetMounts()
- if err != nil {
- return "", err
- }
- for _, mount := range mounts {
- if mount.Fstype == "cgroup" {
- for _, opt := range strings.Split(mount.VfsOpts, ",") {
- if opt == subsystem {
- return mount.Mountpoint, nil
- }
- }
- }
- }
- return "", fmt.Errorf("cgroup mountpoint not found for %s", subsystem)
- }
- // Returns the relative path to the cgroup docker is running in.
- func getThisCgroupDir(subsystem string) (string, error) {
- f, err := os.Open("/proc/self/cgroup")
- if err != nil {
- return "", err
- }
- defer f.Close()
- return parseCgroupFile(subsystem, f)
- }
- func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
- s := bufio.NewScanner(r)
- for s.Scan() {
- if err := s.Err(); err != nil {
- return "", err
- }
- text := s.Text()
- parts := strings.Split(text, ":")
- if parts[1] == subsystem {
- return parts[2], nil
- }
- }
- return "", fmt.Errorf("cgroup '%s' not found in /proc/self/cgroup", subsystem)
- }
- // Returns a list of pids for the given container.
- func GetPidsForContainer(id string) ([]int, error) {
- pids := []int{}
- // memory is chosen randomly, any cgroup used by docker works
- subsystem := "memory"
- cgroupRoot, err := FindCgroupMountpoint(subsystem)
- if err != nil {
- return pids, err
- }
- cgroupDir, err := getThisCgroupDir(subsystem)
- if err != nil {
- return pids, err
- }
- filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
- if _, err := os.Stat(filename); os.IsNotExist(err) {
- // With more recent lxc versions use, cgroup will be in lxc/
- filename = filepath.Join(cgroupRoot, cgroupDir, "lxc", id, "tasks")
- }
- output, err := ioutil.ReadFile(filename)
- if err != nil {
- return pids, err
- }
- for _, p := range strings.Split(string(output), "\n") {
- if len(p) == 0 {
- continue
- }
- pid, err := strconv.Atoi(p)
- if err != nil {
- return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
- }
- pids = append(pids, pid)
- }
- return pids, nil
- }
|