github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/prometheus/procfs/proc.go (about) 1 // Copyright 2018 The Prometheus Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package procfs 15 16 import ( 17 "bytes" 18 "fmt" 19 "io/ioutil" 20 "os" 21 "strconv" 22 "strings" 23 ) 24 25 // Proc provides information about a running process. 26 type Proc struct { 27 // The process ID. 28 PID int 29 30 fs FS 31 } 32 33 // Procs represents a list of Proc structs. 34 type Procs []Proc 35 36 func (p Procs) Len() int { return len(p) } 37 func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 38 func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } 39 40 // Self returns a process for the current process read via /proc/self. 41 func Self() (Proc, error) { 42 fs, err := NewFS(DefaultMountPoint) 43 if err != nil { 44 return Proc{}, err 45 } 46 return fs.Self() 47 } 48 49 // NewProc returns a process for the given pid under /proc. 50 func NewProc(pid int) (Proc, error) { 51 fs, err := NewFS(DefaultMountPoint) 52 if err != nil { 53 return Proc{}, err 54 } 55 return fs.NewProc(pid) 56 } 57 58 // AllProcs returns a list of all currently available processes under /proc. 59 func AllProcs() (Procs, error) { 60 fs, err := NewFS(DefaultMountPoint) 61 if err != nil { 62 return Procs{}, err 63 } 64 return fs.AllProcs() 65 } 66 67 // Self returns a process for the current process. 68 func (fs FS) Self() (Proc, error) { 69 p, err := os.Readlink(fs.Path("self")) 70 if err != nil { 71 return Proc{}, err 72 } 73 pid, err := strconv.Atoi(strings.Replace(p, string(fs), "", -1)) 74 if err != nil { 75 return Proc{}, err 76 } 77 return fs.NewProc(pid) 78 } 79 80 // NewProc returns a process for the given pid. 81 func (fs FS) NewProc(pid int) (Proc, error) { 82 if _, err := os.Stat(fs.Path(strconv.Itoa(pid))); err != nil { 83 return Proc{}, err 84 } 85 return Proc{PID: pid, fs: fs}, nil 86 } 87 88 // AllProcs returns a list of all currently available processes. 89 func (fs FS) AllProcs() (Procs, error) { 90 d, err := os.Open(fs.Path()) 91 if err != nil { 92 return Procs{}, err 93 } 94 defer d.Close() 95 96 names, err := d.Readdirnames(-1) 97 if err != nil { 98 return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err) 99 } 100 101 p := Procs{} 102 for _, n := range names { 103 pid, err := strconv.ParseInt(n, 10, 64) 104 if err != nil { 105 continue 106 } 107 p = append(p, Proc{PID: int(pid), fs: fs}) 108 } 109 110 return p, nil 111 } 112 113 // CmdLine returns the command line of a process. 114 func (p Proc) CmdLine() ([]string, error) { 115 f, err := os.Open(p.path("cmdline")) 116 if err != nil { 117 return nil, err 118 } 119 defer f.Close() 120 121 data, err := ioutil.ReadAll(f) 122 if err != nil { 123 return nil, err 124 } 125 126 if len(data) < 1 { 127 return []string{}, nil 128 } 129 130 return strings.Split(string(bytes.TrimRight(data, string("\x00"))), string(byte(0))), nil 131 } 132 133 // Comm returns the command name of a process. 134 func (p Proc) Comm() (string, error) { 135 f, err := os.Open(p.path("comm")) 136 if err != nil { 137 return "", err 138 } 139 defer f.Close() 140 141 data, err := ioutil.ReadAll(f) 142 if err != nil { 143 return "", err 144 } 145 146 return strings.TrimSpace(string(data)), nil 147 } 148 149 // Executable returns the absolute path of the executable command of a process. 150 func (p Proc) Executable() (string, error) { 151 exe, err := os.Readlink(p.path("exe")) 152 if os.IsNotExist(err) { 153 return "", nil 154 } 155 156 return exe, err 157 } 158 159 // Cwd returns the absolute path to the current working directory of the process. 160 func (p Proc) Cwd() (string, error) { 161 wd, err := os.Readlink(p.path("cwd")) 162 if os.IsNotExist(err) { 163 return "", nil 164 } 165 166 return wd, err 167 } 168 169 // RootDir returns the absolute path to the process's root directory (as set by chroot) 170 func (p Proc) RootDir() (string, error) { 171 rdir, err := os.Readlink(p.path("root")) 172 if os.IsNotExist(err) { 173 return "", nil 174 } 175 176 return rdir, err 177 } 178 179 // FileDescriptors returns the currently open file descriptors of a process. 180 func (p Proc) FileDescriptors() ([]uintptr, error) { 181 names, err := p.fileDescriptors() 182 if err != nil { 183 return nil, err 184 } 185 186 fds := make([]uintptr, len(names)) 187 for i, n := range names { 188 fd, err := strconv.ParseInt(n, 10, 32) 189 if err != nil { 190 return nil, fmt.Errorf("could not parse fd %s: %s", n, err) 191 } 192 fds[i] = uintptr(fd) 193 } 194 195 return fds, nil 196 } 197 198 // FileDescriptorTargets returns the targets of all file descriptors of a process. 199 // If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string. 200 func (p Proc) FileDescriptorTargets() ([]string, error) { 201 names, err := p.fileDescriptors() 202 if err != nil { 203 return nil, err 204 } 205 206 targets := make([]string, len(names)) 207 208 for i, name := range names { 209 target, err := os.Readlink(p.path("fd", name)) 210 if err == nil { 211 targets[i] = target 212 } 213 } 214 215 return targets, nil 216 } 217 218 // FileDescriptorsLen returns the number of currently open file descriptors of 219 // a process. 220 func (p Proc) FileDescriptorsLen() (int, error) { 221 fds, err := p.fileDescriptors() 222 if err != nil { 223 return 0, err 224 } 225 226 return len(fds), nil 227 } 228 229 // MountStats retrieves statistics and configuration for mount points in a 230 // process's namespace. 231 func (p Proc) MountStats() ([]*Mount, error) { 232 f, err := os.Open(p.path("mountstats")) 233 if err != nil { 234 return nil, err 235 } 236 defer f.Close() 237 238 return parseMountStats(f) 239 } 240 241 func (p Proc) fileDescriptors() ([]string, error) { 242 d, err := os.Open(p.path("fd")) 243 if err != nil { 244 return nil, err 245 } 246 defer d.Close() 247 248 names, err := d.Readdirnames(-1) 249 if err != nil { 250 return nil, fmt.Errorf("could not read %s: %s", d.Name(), err) 251 } 252 253 return names, nil 254 } 255 256 func (p Proc) path(pa ...string) string { 257 return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) 258 }