shirou_gopsutil/process/process_posix.go

133 lines
2.6 KiB
Go
Raw Normal View History

// +build linux freebsd openbsd darwin
2014-12-30 21:09:05 +08:00
package process
import (
"os"
"os/exec"
"os/user"
"path/filepath"
"strconv"
"strings"
"syscall"
"github.com/shirou/gopsutil/internal/common"
)
// POSIX
func getTerminalMap() (map[uint64]string, error) {
ret := make(map[uint64]string)
2014-04-30 15:16:07 +08:00
var termfiles []string
d, err := os.Open("/dev")
if err != nil {
return nil, err
}
defer d.Close()
devnames, err := d.Readdirnames(-1)
for _, devname := range devnames {
if strings.HasPrefix(devname, "/dev/tty") {
termfiles = append(termfiles, "/dev/tty/"+devname)
}
}
var ptsnames []string
ptsd, err := os.Open("/dev/pts")
if err != nil {
ptsnames, _ = filepath.Glob("/dev/ttyp*")
if ptsnames == nil {
return nil, err
}
}
2017-02-22 21:46:23 +08:00
defer ptsd.Close()
if ptsnames == nil {
defer ptsd.Close()
ptsnames, err = ptsd.Readdirnames(-1)
for _, ptsname := range ptsnames {
termfiles = append(termfiles, "/dev/pts/"+ptsname)
}
} else {
termfiles = ptsnames
}
for _, name := range termfiles {
stat := syscall.Stat_t{}
if err = syscall.Stat(name, &stat); err != nil {
return nil, err
}
2014-04-24 18:14:00 +08:00
rdev := uint64(stat.Rdev)
ret[rdev] = strings.Replace(name, "/dev", "", -1)
}
return ret, nil
}
// SendSignal sends a syscall.Signal to the process.
// Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported.
2014-04-30 15:16:07 +08:00
func (p *Process) SendSignal(sig syscall.Signal) error {
sigAsStr := "INT"
switch sig {
case syscall.SIGSTOP:
2014-04-30 15:16:07 +08:00
sigAsStr = "STOP"
case syscall.SIGCONT:
2014-04-30 15:16:07 +08:00
sigAsStr = "CONT"
case syscall.SIGTERM:
2014-04-30 15:16:07 +08:00
sigAsStr = "TERM"
case syscall.SIGKILL:
2014-04-30 15:16:07 +08:00
sigAsStr = "KILL"
}
kill, err := exec.LookPath("kill")
if err != nil {
2016-04-01 21:22:03 +08:00
return err
}
cmd := exec.Command(kill, "-s", sigAsStr, strconv.Itoa(int(p.Pid)))
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return err
}
err = common.WaitTimeout(cmd, common.Timeout)
if err != nil {
return err
}
return nil
}
// Suspend sends SIGSTOP to the process.
func (p *Process) Suspend() error {
2014-04-30 15:16:07 +08:00
return p.SendSignal(syscall.SIGSTOP)
}
// Resume sends SIGCONT to the process.
func (p *Process) Resume() error {
2014-04-30 15:16:07 +08:00
return p.SendSignal(syscall.SIGCONT)
}
// Terminate sends SIGTERM to the process.
func (p *Process) Terminate() error {
2014-04-30 15:16:07 +08:00
return p.SendSignal(syscall.SIGTERM)
}
// Kill sends SIGKILL to the process.
func (p *Process) Kill() error {
2014-04-30 15:16:07 +08:00
return p.SendSignal(syscall.SIGKILL)
}
// Username returns a username of the process.
func (p *Process) Username() (string, error) {
uids, err := p.Uids()
if err != nil {
return "", err
}
if len(uids) > 0 {
u, err := user.LookupId(strconv.Itoa(int(uids[0])))
if err != nil {
return "", err
}
return u.Username, nil
}
return "", nil
}