您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

52 行
1.7 KiB

  1. import errno
  2. import subprocess
  3. import sys
  4. from ._core import Process
  5. class PsNotAvailable(EnvironmentError):
  6. pass
  7. def iter_process_parents(pid, max_depth=10):
  8. """Try to look up the process tree via the output of `ps`."""
  9. try:
  10. cmd = ["ps", "-ww", "-o", "pid=", "-o", "ppid=", "-o", "args="]
  11. output = subprocess.check_output(cmd)
  12. except OSError as e: # Python 2-compatible FileNotFoundError.
  13. if e.errno != errno.ENOENT:
  14. raise
  15. raise PsNotAvailable("ps not found")
  16. except subprocess.CalledProcessError as e:
  17. # `ps` can return 1 if the process list is completely empty.
  18. # (sarugaku/shellingham#15)
  19. if not e.output.strip():
  20. return
  21. raise
  22. if not isinstance(output, str):
  23. encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
  24. output = output.decode(encoding)
  25. processes_mapping = {}
  26. for line in output.split("\n"):
  27. try:
  28. _pid, ppid, args = line.strip().split(None, 2)
  29. # XXX: This is not right, but we are really out of options.
  30. # ps does not offer a sane way to decode the argument display,
  31. # and this is "Good Enough" for obtaining shell names. Hopefully
  32. # people don't name their shell with a space, or have something
  33. # like "/usr/bin/xonsh is uber". (sarugaku/shellingham#14)
  34. args = tuple(a.strip() for a in args.split(" "))
  35. except ValueError:
  36. continue
  37. processes_mapping[_pid] = Process(args=args, pid=_pid, ppid=ppid)
  38. for _ in range(max_depth):
  39. try:
  40. process = processes_mapping[pid]
  41. except KeyError:
  42. return
  43. yield process
  44. pid = process.ppid