Merge pull request #167 from cgilling/cmdline_slice

process: add CmdlineSlice function for linux + freebsd
This commit is contained in:
shirou 2016-02-29 21:57:08 +09:00
commit 1ab11f7afd
5 changed files with 96 additions and 0 deletions

View File

@ -81,6 +81,9 @@ func (p *Process) Name() (string, error) {
func (p *Process) Exe() (string, error) {
return "", common.NotImplementedError
}
// Cmdline returns the command line arguments of the process as a string with
// each argument separated by 0x20 ascii character.
func (p *Process) Cmdline() (string, error) {
r, err := callPs("command", p.Pid, false)
if err != nil {
@ -88,6 +91,19 @@ func (p *Process) Cmdline() (string, error) {
}
return strings.Join(r[0], " "), err
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument. Because of current deficiencies in the way that the command
// line arguments are found, single arguments that have spaces in the will actually be
// reported as two separate items. In order to do something better CGO would be needed
// to use the native darwin functions.
func (p *Process) CmdlineSlice() ([]string, error) {
r, err := callPs("command", p.Pid, false)
if err != nil {
return nil, err
}
return r[0], err
}
func (p *Process) CreateTime() (int64, error) {
return 0, common.NotImplementedError
}

View File

@ -54,6 +54,7 @@ func (p *Process) Name() (string, error) {
func (p *Process) Exe() (string, error) {
return "", common.NotImplementedError
}
func (p *Process) Cmdline() (string, error) {
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
@ -69,6 +70,27 @@ func (p *Process) Cmdline() (string, error) {
return strings.Join(ret, " "), nil
}
func (p *Process) CmdlineSlice() ([]string, error) {
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return nil, err
}
if len(buf) == 0 {
return nil, nil
}
if buf[len(buf)-1] == 0 {
buf = buf[:len(buf)-1]
}
parts := bytes.Split(buf, []byte{0})
var strParts []string
for _, p := range parts {
strParts = append(strParts, string(p))
}
return strParts, nil
}
func (p *Process) CreateTime() (int64, error) {
return 0, common.NotImplementedError
}

View File

@ -3,6 +3,7 @@
package process
import (
"bytes"
"encoding/json"
"errors"
"fmt"
@ -91,9 +92,19 @@ func (p *Process) Name() (string, error) {
func (p *Process) Exe() (string, error) {
return p.fillFromExe()
}
// Cmdline returns the command line arguments of the process as a string with
// each argument separated by 0x20 ascii character.
func (p *Process) Cmdline() (string, error) {
return p.fillFromCmdline()
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument.
func (p *Process) CmdlineSlice() ([]string, error) {
return p.fillSliceFromCmdline()
}
func (p *Process) CreateTime() (int64, error) {
_, _, _, createTime, _, err := p.fillFromStat()
if err != nil {
@ -410,6 +421,28 @@ func (p *Process) fillFromCmdline() (string, error) {
return strings.Join(ret, " "), nil
}
func (p *Process) fillSliceFromCmdline() ([]string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return nil, err
}
if len(cmdline) == 0 {
return nil, nil
}
if cmdline[len(cmdline)-1] == 0 {
cmdline = cmdline[:len(cmdline)-1]
}
parts := bytes.Split(cmdline, []byte{0})
var strParts []string
for _, p := range parts {
strParts = append(strParts, string(p))
}
return strParts, nil
}
// Get IO status from /proc/(pid)/io
func (p *Process) fillFromIO() (*IOCountersStat, error) {
pid := p.Pid

View File

@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/user"
"reflect"
"runtime"
"strings"
"sync"
@ -120,6 +121,18 @@ func Test_Process_CmdLine(t *testing.T) {
}
}
func Test_Process_CmdLineSlice(t *testing.T) {
p := testGetProcess()
v, err := p.CmdlineSlice()
if err != nil {
t.Fatalf("geting cmdline slice error %v", err)
}
if !reflect.DeepEqual(v, os.Args) {
t.Errorf("returned cmdline slice not as expected:\nexp: %v\ngot: %v", os.Args, v)
}
}
func Test_Process_Ppid(t *testing.T) {
p := testGetProcess()

View File

@ -5,6 +5,7 @@ package process
import (
"errors"
"fmt"
"strings"
"syscall"
"time"
"unsafe"
@ -145,6 +146,17 @@ func (p *Process) Cmdline() (string, error) {
return *dst[0].CommandLine, nil
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument. This merely returns the CommandLine informations passed
// to the process split on the 0x20 ASCII character.
func (p *Process) CmdlineSlice() ([]string, error) {
cmdline, err := p.Cmdline()
if err != nil {
return nil, err
}
return strings.Split(cmdline, " "), nil
}
func (p *Process) CreateTime() (int64, error) {
dst, err := GetWin32Proc(p.Pid)
if err != nil {