Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Expose environment #396

Open
tejasmanohar opened this issue Jul 10, 2017 · 9 comments
Open

Suggestion: Expose environment #396

tejasmanohar opened this issue Jul 10, 2017 · 9 comments

Comments

@tejasmanohar
Copy link

Would be useful to expose environment variables a la psutil.Process().environ() in Python

@shirou
Copy link
Owner

shirou commented Jul 11, 2017

Thank you for your suggestion.

  • FreeBSD: procstat -e
  • Mac OS X: ps eww
  • Windows:
    • powershell: (Get-Process -id ).StartInfo.EnvironmentVariables
    • syscall.GetEnvironmentStrings() can not used because it returns only that process information.
    • kernel32's ReadProcessMemory function

Hmm, so I can get environment variable and psutils also have that method, I will try to add. But I can not promise when to start.

@tejasmanohar
Copy link
Author

@shirou I will send PR for OS X soon :)

@dastergon
Copy link

Hi @tejasmanohar, Any updates on this feature implementation? I find it a really useful

@tejasmanohar
Copy link
Author

Sorry, got busy with other things :\

@Ferguzz
Copy link

Ferguzz commented Dec 10, 2018

i would find this feature very useful

@tejasmanohar
Copy link
Author

I no longer need it so probably not gonna submit a PR in near future. Feel free to tackle!

@Lomanic
Copy link
Collaborator

Lomanic commented Dec 12, 2018

Thinking about implementing this, we will return a map[string]string. I'm quite unsure how to parse ps -p $PID eww -o command= (darwin), as it includes the executable path and there might be spaces in this path and in variables, will need some testing.

Re: Linux, there is /proc/$PID/environ, as used in psutil, even if it is not updated after process init (option would be to attach a debugger like gdb but this is out of the question).

@Lomanic
Copy link
Collaborator

Lomanic commented Dec 13, 2018

Related psutil issue giampaolo/psutil#52

@Ferguzz
Copy link

Ferguzz commented Dec 14, 2018

psutil use a sysctl call to get the environ. with some finessing this code will do the job.

package main

import (
	"bytes"
	"encoding/binary"
	"golang.org/x/sys/unix"
	"syscall"
	"unsafe"
)

const (
	CTL_KERN       = 1
	KERN_ARGMAX    = 8
	KERN_PROCARGS2 = 49
)

func sysctl(mib []int32, out unsafe.Pointer, n uintptr) syscall.Errno {
	_, _, e := unix.Syscall6(
		unix.SYS___SYSCTL,
		uintptr(unsafe.Pointer(&mib[0])),
		uintptr(len(mib)),
		uintptr(out),
		uintptr(unsafe.Pointer(&n)),
		uintptr(unsafe.Pointer(nil)),
		0,
	)
	return e
}

func Environ(pid int32) (map[string]string, error) {
	var argmax int32
	if err := sysctl([]int32{CTL_KERN, KERN_ARGMAX}, unsafe.Pointer(&argmax), unsafe.Sizeof(argmax)); err != 0 {
		return nil, err
	}

	procargs := make([]byte, argmax)
	if err := sysctl([]int32{CTL_KERN, KERN_PROCARGS2, pid}, unsafe.Pointer(&procargs[0]), uintptr(argmax)); err != 0 {
		return nil, err
	}

	var argc uint32
	argc = binary.LittleEndian.Uint32(procargs[:unsafe.Sizeof(argc)])
	procargs = procargs[unsafe.Sizeof(argc):]

	// the command portion is terminated with a null byte
	argsIndex := bytes.Index(procargs, []byte("\000"))

        // arguments and environment vars are also null byte seperated
	args := bytes.Split(procargs[argsIndex:], []byte("\000"))

	// find the end of the argv portion of the output
	environIndex := 0
	for ; argc > 0; environIndex++ {
		if !bytes.Equal(args[environIndex], nil) {
			argc--
		}
	}

	environ := make(map[string]string)
	for _, env := range args[environIndex:] {
		if !bytes.Equal(env, nil) {
			kv := bytes.Split(env, []byte("="))
			environ[string(kv[0])] = string(kv[1])
		}
	}

	return environ, nil
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants