Merge pull request #83 from mattrose/issue80
rely on python psutil to get the cwd
This commit is contained in:
commit
d6bb7bec97
|
@ -6,22 +6,16 @@
|
||||||
>>> cwd.__class__.__name__
|
>>> cwd.__class__.__name__
|
||||||
'str'
|
'str'
|
||||||
>>> func = get_pid_cwd()
|
>>> func = get_pid_cwd()
|
||||||
>>> func.__class__.__name__
|
>>> cwd.__class__.__name__
|
||||||
'function'
|
'str'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
from .util import dbg, err
|
|
||||||
|
|
||||||
try:
|
|
||||||
import psutil
|
import psutil
|
||||||
psutil_avail = True
|
from .util import dbg, err
|
||||||
except (ImportError):
|
|
||||||
dbg('psutil not found')
|
|
||||||
psutil_avail = False
|
|
||||||
|
|
||||||
def get_default_cwd():
|
def get_default_cwd():
|
||||||
"""Determine a reasonable default cwd"""
|
"""Determine a reasonable default cwd"""
|
||||||
|
@ -35,51 +29,6 @@ def get_default_cwd():
|
||||||
|
|
||||||
def get_pid_cwd():
|
def get_pid_cwd():
|
||||||
"""Determine an appropriate cwd function for the OS we are running on"""
|
"""Determine an appropriate cwd function for the OS we are running on"""
|
||||||
|
return psutil.Process().as_dict()['cwd']
|
||||||
func = lambda pid: None
|
|
||||||
system = platform.system()
|
|
||||||
|
|
||||||
if system == 'Linux':
|
|
||||||
dbg('Using Linux get_pid_cwd')
|
|
||||||
func = linux_get_pid_cwd
|
|
||||||
elif system == 'FreeBSD':
|
|
||||||
try:
|
|
||||||
from . import freebsd
|
|
||||||
func = freebsd.get_process_cwd
|
|
||||||
dbg('Using FreeBSD get_pid_cwd')
|
|
||||||
except (OSError, NotImplementedError, ImportError):
|
|
||||||
dbg('FreeBSD version too old for get_pid_cwd')
|
|
||||||
elif system == 'SunOS':
|
|
||||||
dbg('Using SunOS get_pid_cwd')
|
|
||||||
func = sunos_get_pid_cwd
|
|
||||||
elif psutil_avail:
|
|
||||||
func = psutil_cwd
|
|
||||||
else:
|
|
||||||
dbg('Unable to determine a get_pid_cwd for OS: %s' % system)
|
|
||||||
|
|
||||||
return(func)
|
|
||||||
|
|
||||||
def proc_get_pid_cwd(pid, path):
|
|
||||||
"""Extract the cwd of a PID from proc, given the PID and the /proc path to
|
|
||||||
insert it into, e.g. /proc/%s/cwd"""
|
|
||||||
try:
|
|
||||||
cwd = os.path.realpath(path % pid)
|
|
||||||
except Exception as ex:
|
|
||||||
err('Unable to get cwd for PID %s: %s' % (pid, ex))
|
|
||||||
cwd = '/'
|
|
||||||
|
|
||||||
return(cwd)
|
|
||||||
|
|
||||||
def linux_get_pid_cwd(pid):
|
|
||||||
"""Determine the cwd for a given PID on Linux kernels"""
|
|
||||||
return(proc_get_pid_cwd(pid, '/proc/%s/cwd'))
|
|
||||||
|
|
||||||
def sunos_get_pid_cwd(pid):
|
|
||||||
"""Determine the cwd for a given PID on SunOS kernels"""
|
|
||||||
return(proc_get_pid_cwd(pid, '/proc/%s/path/cwd'))
|
|
||||||
|
|
||||||
def psutil_cwd(pid):
|
|
||||||
"""Determine the cwd using psutil which also supports Darwin"""
|
|
||||||
return psutil.Process(pid).as_dict()['cwd']
|
|
||||||
|
|
||||||
# vim: set expandtab ts=4 sw=4:
|
# vim: set expandtab ts=4 sw=4:
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008, Thomas Hurst <tom@hur.st>
|
|
||||||
#
|
|
||||||
# Use of this file is unrestricted provided this notice is retained.
|
|
||||||
# If you use it, it'd be nice if you dropped me a note. Also beer.
|
|
||||||
|
|
||||||
"""
|
|
||||||
freebsd.get_process_cwd(pid):
|
|
||||||
Use sysctl() to retrieve the cwd of an arbitrary process on FreeBSD
|
|
||||||
using kern.proc.filedesc, as used by procstat(1).
|
|
||||||
Tested on FreeBSD 7-STABLE/amd64 from April 11 2008.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import platform
|
|
||||||
from ctypes import *
|
|
||||||
from ctypes.util import find_library
|
|
||||||
|
|
||||||
class sockaddr_storage(Structure):
|
|
||||||
"""struct sockaddr_storage, defined in /usr/include/sys/socket.h"""
|
|
||||||
_fields_ = [
|
|
||||||
('ss_len', c_char),
|
|
||||||
('ss_family', c_char), # /usr/include/sys/_types.h; _uint8_t
|
|
||||||
('__ss_pad1', c_char * 6), # (sizeof(int64) - sizeof(char) - sizeof(ss_family_t))
|
|
||||||
('__ss_align', c_longlong),
|
|
||||||
('__ss_pad2', c_char * 112), # (128(maxsize) - sizeof(char) - sizeof(ss_family_t) -
|
|
||||||
# sizeof(ss_pad1) - sizeof(int64))
|
|
||||||
]
|
|
||||||
|
|
||||||
class kinfo_file(Structure):
|
|
||||||
"""struct kinfo_file, defined in /usr/include/sys/user.h """
|
|
||||||
_fields_ = [
|
|
||||||
('kf_structsize', c_int),
|
|
||||||
('kf_type', c_int),
|
|
||||||
('kf_fd', c_int),
|
|
||||||
('kf_ref_count', c_int),
|
|
||||||
('kf_flags', c_int),
|
|
||||||
('kf_offset', c_size_t), # this is a off_t, a pointer
|
|
||||||
('kf_vnode_type', c_int),
|
|
||||||
('kf_sock_domain', c_int),
|
|
||||||
('kf_sock_type', c_int),
|
|
||||||
('kf_sock_protocol', c_int),
|
|
||||||
('kf_path', c_char * 1024), # PATH_MAX
|
|
||||||
('kf_sa_local', sockaddr_storage),
|
|
||||||
('kf_sa_peer', sockaddr_storage),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def get_process_cwd(pid):
|
|
||||||
"""Return string containing the current working directory of the given pid,
|
|
||||||
or None on failure."""
|
|
||||||
# /usr/include/sys/sysctl.h
|
|
||||||
# CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC
|
|
||||||
oid = (c_uint * 4)(1, 14, 14, pid)
|
|
||||||
|
|
||||||
if libc.sysctl(oid, 4, None, byref(uintlen), None, 0) < 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
buf = c_char_p(" " * uintlen.value)
|
|
||||||
if libc.sysctl(oid, 4, buf, byref(uintlen), None, 0) < 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
kifs = cast(buf, POINTER(kinfo_file))
|
|
||||||
for i in range(0, uintlen.value / sizeof(kinfo_file)):
|
|
||||||
kif = kifs[i]
|
|
||||||
if kif.kf_fd == -1: # KF_FD_TYPE_CWD
|
|
||||||
return kif.kf_path
|
|
||||||
|
|
||||||
|
|
||||||
if platform.system() in ['FreeBSD', 'OpenBSD']:
|
|
||||||
libc = CDLL(find_library('c'))
|
|
||||||
|
|
||||||
uintlen = c_size_t(sizeof(c_uint))
|
|
||||||
ver = c_uint(0)
|
|
||||||
|
|
||||||
if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(uintlen), None, 0) < 0):
|
|
||||||
raise OSError("sysctlbyname returned < 0")
|
|
||||||
|
|
||||||
# kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions
|
|
||||||
if ver.value < 700104 and ver.value < 800019:
|
|
||||||
raise NotImplementedError("cwd detection requires a recent 7.0-STABLE or 8-CURRENT")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import os, sys
|
|
||||||
print(" => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid())))
|
|
||||||
for pid in sys.argv:
|
|
||||||
try:
|
|
||||||
pid = int(pid)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
print(" => %d cwd = %s" % (pid, get_process_cwd(pid)))
|
|
||||||
|
|
Loading…
Reference in New Issue