<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>stem.util.system — Stem 1.1.0 documentation</title> <link rel="stylesheet" href="../../../_static/haiku.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/print.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../../../', VERSION: '1.1.0', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="../../../_static/jquery.js"></script> <script type="text/javascript" src="../../../_static/underscore.js"></script> <script type="text/javascript" src="../../../_static/doctools.js"></script> <script type="text/javascript" src="../../../_static/theme_extras.js"></script> <link rel="shortcut icon" href="../../../_static/favicon.png"/> <link rel="top" title="Stem 1.1.0 documentation" href="../../../index.html" /> <link rel="up" title="stem" href="../../stem.html" /> </head> <body> <div class="header"><img class="rightlogo" src="../../../_static/logo.png" alt="Logo"/><h1 class="heading"><a href="../../../index.html"> <span>Stem Docs</span></a></h1> <h2 class="heading"><span>stem.util.system</span></h2> </div> <div class="topnav"> <p> <ul id="navbar"> <li><a href="../../../index.html">Home</a></li> <li><a href="../../../tutorials.html">Tutorials</a> <ul> <li><a href="../../../tutorials/the_little_relay_that_could.html">Hello World</a></li> <li><a href="../../../tutorials/to_russia_with_love.html">Client Usage</a></li> <li><a href="../../../tutorials/tortoise_and_the_hare.html">Event Listening</a></li> <li><a href="../../../tutorials/mirror_mirror_on_the_wall.html">Tor Descriptors</a></li> <li><a href="../../../tutorials/east_of_the_sun.html">Utilities</a></li> <li><a href="../../../tutorials/double_double_toil_and_trouble.html">Examples</a></li> </ul> </li> <li><a href="../../../api.html">API</a> <ul> <li><a href="../../../api/control.html">stem.control</a></li> <li><a href="../../../api/connection.html">stem.connection</a></li> <li><a href="../../../api/socket.html">stem.socket</a></li> <li><a href="../../../api/process.html">stem.process</a></li> <li><a href="../../../api/response.html">stem.response</a></li> <li><a href="../../../api/exit_policy.html">stem.exit_policy</a></li> <li><a href="../../../api/version.html">stem.version</a></li> <li><a href="../../../api.html#descriptors">Descriptors</a></li> <li><a href="../../../api.html#utilities">Utilities</a></li> </ul> </li> <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem">Development</a> <ul> <li><a href="../../../faq.html">FAQ</a></li> <li><a href="../../../change_log.html">Change Log</a></li> <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem/bugs">Bug Tracker</a></li> <li><a href="../../../download.html">Download</a></li> </ul> </li> </ul> </p> </div> <div class="content"> <h1>Source code for stem.util.system</h1><div class="highlight"><pre> <span class="c"># Copyright 2011-2013, Damian Johnson and The Tor Project</span> <span class="c"># See LICENSE for licensing information</span> <span class="sd">"""</span> <span class="sd">Helper functions for working with the underlying system. These are mostly os</span> <span class="sd">dependent, only working on linux, osx, and bsd. In almost all cases they're</span> <span class="sd">best-effort, providing **None** if the lookup fails.</span> <span class="sd">**Module Overview:**</span> <span class="sd">::</span> <span class="sd"> is_windows - checks if we're running on windows</span> <span class="sd"> is_mac - checks if we're running on a mac</span> <span class="sd"> is_bsd - checks if we're running on the bsd family of operating systems</span> <span class="sd"> is_available - determines if a command is available on this system</span> <span class="sd"> is_running - determines if a given process is running</span> <span class="sd"> get_name_by_pid - gets the name for a process by the given pid</span> <span class="sd"> get_pid_by_name - gets the pid for a process by the given name</span> <span class="sd"> get_pid_by_port - gets the pid for a process listening to a given port</span> <span class="sd"> get_pid_by_open_file - gets the pid for the process with an open file</span> <span class="sd"> get_cwd - provides the current working directory for a given process</span> <span class="sd"> get_user - provides the user a process is running under</span> <span class="sd"> get_start_time - provides the unix timestamp when the process started</span> <span class="sd"> get_bsd_jail_id - provides the BSD jail id a given process is running within</span> <span class="sd"> get_bsd_jail_path - provides the path of the given BSD jail</span> <span class="sd"> expand_path - expands relative paths and ~ entries</span> <span class="sd"> call - runs the given system command and provides back the results</span> <span class="sd"> get_process_name - provides our process' name</span> <span class="sd"> set_process_name - changes our process' name</span> <span class="sd">"""</span> <span class="kn">import</span> <span class="nn">ctypes</span> <span class="kn">import</span> <span class="nn">ctypes.util</span> <span class="kn">import</span> <span class="nn">os</span> <span class="kn">import</span> <span class="nn">platform</span> <span class="kn">import</span> <span class="nn">pwd</span> <span class="kn">import</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="nn">time</span> <span class="kn">import</span> <span class="nn">stem.util.proc</span> <span class="kn">import</span> <span class="nn">stem.util.str_tools</span> <span class="kn">from</span> <span class="nn">stem</span> <span class="kn">import</span> <span class="n">UNDEFINED</span> <span class="kn">from</span> <span class="nn">stem.util</span> <span class="kn">import</span> <span class="n">log</span> <span class="c"># Mapping of commands to if they're available or not.</span> <span class="n">CMD_AVAILABLE_CACHE</span> <span class="o">=</span> <span class="p">{}</span> <span class="c"># An incomplete listing of commands provided by the shell. Expand this as</span> <span class="c"># needed. Some noteworthy things about shell commands...</span> <span class="c">#</span> <span class="c"># * They're not in the path so is_available() will fail.</span> <span class="c"># * subprocess.Popen() without the 'shell = True' argument will fail with...</span> <span class="c"># OSError: [Errno 2] No such file or directory</span> <span class="n">SHELL_COMMANDS</span> <span class="o">=</span> <span class="p">[</span><span class="s">'ulimit'</span><span class="p">]</span> <span class="n">IS_RUNNING_PS_LINUX</span> <span class="o">=</span> <span class="s">"ps -A co command"</span> <span class="n">IS_RUNNING_PS_BSD</span> <span class="o">=</span> <span class="s">"ps -ao ucomm="</span> <span class="n">GET_NAME_BY_PID_PS</span> <span class="o">=</span> <span class="s">"ps -p </span><span class="si">%s</span><span class="s"> -o comm"</span> <span class="n">GET_PID_BY_NAME_PGREP</span> <span class="o">=</span> <span class="s">"pgrep -x </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_PID_BY_NAME_PIDOF</span> <span class="o">=</span> <span class="s">"pidof </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_PID_BY_NAME_PS_LINUX</span> <span class="o">=</span> <span class="s">"ps -o pid -C </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_PID_BY_NAME_PS_BSD</span> <span class="o">=</span> <span class="s">"ps axc"</span> <span class="n">GET_PID_BY_NAME_LSOF</span> <span class="o">=</span> <span class="s">"lsof -tc </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_PID_BY_PORT_NETSTAT</span> <span class="o">=</span> <span class="s">"netstat -npltu"</span> <span class="n">GET_PID_BY_PORT_SOCKSTAT</span> <span class="o">=</span> <span class="s">"sockstat -4l -P tcp -p </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_PID_BY_PORT_LSOF</span> <span class="o">=</span> <span class="s">"lsof -wnP -iTCP -sTCP:LISTEN"</span> <span class="n">GET_PID_BY_FILE_LSOF</span> <span class="o">=</span> <span class="s">"lsof -tw </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_CWD_PWDX</span> <span class="o">=</span> <span class="s">"pwdx </span><span class="si">%s</span><span class="s">"</span> <span class="n">GET_CWD_LSOF</span> <span class="o">=</span> <span class="s">"lsof -a -p </span><span class="si">%s</span><span class="s"> -d cwd -Fn"</span> <span class="n">GET_BSD_JAIL_ID_PS</span> <span class="o">=</span> <span class="s">"ps -p </span><span class="si">%s</span><span class="s"> -o jid"</span> <span class="n">GET_BSD_JAIL_PATH</span> <span class="o">=</span> <span class="s">"jls -j </span><span class="si">%s</span><span class="s">"</span> <span class="c"># flag for setting the process name, found in '/usr/include/linux/prctl.h'</span> <span class="n">PR_SET_NAME</span> <span class="o">=</span> <span class="mi">15</span> <span class="n">argc_t</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">)</span> <span class="c"># The following can fail with pypy...</span> <span class="c"># AttributeError: No symbol Py_GetArgcArgv found in library <None></span> <span class="k">try</span><span class="p">:</span> <span class="n">Py_GetArgcArgv</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">pythonapi</span><span class="o">.</span><span class="n">Py_GetArgcArgv</span> <span class="n">Py_GetArgcArgv</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="bp">None</span> <span class="n">Py_GetArgcArgv</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">),</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">argc_t</span><span class="p">),</span> <span class="p">]</span> <span class="k">except</span><span class="p">:</span> <span class="n">Py_GetArgcArgv</span> <span class="o">=</span> <span class="bp">None</span> <span class="c"># This is both a cache for get_process_name() and tracks what we've changed our</span> <span class="c"># process name to.</span> <span class="n">_PROCESS_NAME</span> <span class="o">=</span> <span class="bp">None</span> <span class="c"># Length of our original process name.</span> <span class="c">#</span> <span class="c"># The original author our process renaming is based on did a memset for 256,</span> <span class="c"># while Jake did it for the original process name length (capped at 1608). I'm</span> <span class="c"># not sure of the reasons for either of these limits, but setting it to</span> <span class="c"># anything higher than our original name length should be pointless, so opting</span> <span class="c"># for Jake's limit.</span> <span class="n">_MAX_NAME_LENGTH</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <div class="viewcode-block" id="is_windows"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.is_windows">[docs]</a><span class="k">def</span> <span class="nf">is_windows</span><span class="p">():</span> <span class="sd">"""</span> <span class="sd"> Checks if we are running on Windows.</span> <span class="sd"> :returns: **bool** to indicate if we're on Windows</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">==</span> <span class="s">"Windows"</span> </div> <div class="viewcode-block" id="is_mac"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.is_mac">[docs]</a><span class="k">def</span> <span class="nf">is_mac</span><span class="p">():</span> <span class="sd">"""</span> <span class="sd"> Checks if we are running on Mac OSX.</span> <span class="sd"> :returns: **bool** to indicate if we're on a Mac</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">==</span> <span class="s">"Darwin"</span> </div> <div class="viewcode-block" id="is_bsd"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.is_bsd">[docs]</a><span class="k">def</span> <span class="nf">is_bsd</span><span class="p">():</span> <span class="sd">"""</span> <span class="sd"> Checks if we are within the BSD family of operating systems. This presently</span> <span class="sd"> recognizes Macs, FreeBSD, and OpenBSD but may be expanded later.</span> <span class="sd"> :returns: **bool** to indicate if we're on a BSD OS</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"Darwin"</span><span class="p">,</span> <span class="s">"FreeBSD"</span><span class="p">,</span> <span class="s">"OpenBSD"</span><span class="p">)</span> </div> <div class="viewcode-block" id="is_available"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.is_available">[docs]</a><span class="k">def</span> <span class="nf">is_available</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">cached</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Checks the current PATH to see if a command is available or not. If more</span> <span class="sd"> than one command is present (for instance "ls -a | grep foo") then this</span> <span class="sd"> just checks the first.</span> <span class="sd"> Note that shell (like cd and ulimit) aren't in the PATH so this lookup will</span> <span class="sd"> try to assume that it's available. This only happends for recognized shell</span> <span class="sd"> commands (those in SHELL_COMMANDS).</span> <span class="sd"> :param str command: command to search for</span> <span class="sd"> :param bool cached: makes use of available cached results if **True**</span> <span class="sd"> :returns: **True** if an executable we can use by that name exists in the</span> <span class="sd"> PATH, **False** otherwise</span> <span class="sd"> """</span> <span class="k">if</span> <span class="s">" "</span> <span class="ow">in</span> <span class="n">command</span><span class="p">:</span> <span class="n">command</span> <span class="o">=</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">SHELL_COMMANDS</span><span class="p">:</span> <span class="c"># we can't actually look it up, so hope the shell really provides it...</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">elif</span> <span class="n">cached</span> <span class="ow">and</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">CMD_AVAILABLE_CACHE</span><span class="p">:</span> <span class="k">return</span> <span class="n">CMD_AVAILABLE_CACHE</span><span class="p">[</span><span class="n">command</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="n">cmd_exists</span> <span class="o">=</span> <span class="bp">False</span> <span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">"PATH"</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">pathsep</span><span class="p">):</span> <span class="n">cmd_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">command</span><span class="p">)</span> <span class="k">if</span> <span class="n">is_windows</span><span class="p">():</span> <span class="n">cmd_path</span> <span class="o">+=</span> <span class="s">".exe"</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">cmd_path</span><span class="p">)</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">cmd_path</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">X_OK</span><span class="p">):</span> <span class="n">cmd_exists</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">break</span> <span class="n">CMD_AVAILABLE_CACHE</span><span class="p">[</span><span class="n">command</span><span class="p">]</span> <span class="o">=</span> <span class="n">cmd_exists</span> <span class="k">return</span> <span class="n">cmd_exists</span> </div> <div class="viewcode-block" id="is_running"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.is_running">[docs]</a><span class="k">def</span> <span class="nf">is_running</span><span class="p">(</span><span class="n">command</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Checks for if a process with a given name is running or not.</span> <span class="sd"> :param str command: process name to be checked</span> <span class="sd"> :returns: **True** if the process is running, **False** if it's not among ps</span> <span class="sd"> results, and **None** if ps can't be queried</span> <span class="sd"> """</span> <span class="c"># Linux and the BSD families have different variants of ps. Guess based on</span> <span class="c"># the is_bsd() check which to try first, then fall back to the other.</span> <span class="c">#</span> <span class="c"># Linux</span> <span class="c"># -A - Select all processes.</span> <span class="c"># -co command - Shows just the base command.</span> <span class="c">#</span> <span class="c"># Mac / BSD</span> <span class="c"># -a - Display information about other users' processes as well as</span> <span class="c"># our own.</span> <span class="c"># -o ucomm= - Shows just the ucomm attribute ("name to be used for</span> <span class="c"># accounting")</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"ps"</span><span class="p">):</span> <span class="k">if</span> <span class="n">is_bsd</span><span class="p">():</span> <span class="n">primary_resolver</span> <span class="o">=</span> <span class="n">IS_RUNNING_PS_BSD</span> <span class="n">secondary_resolver</span> <span class="o">=</span> <span class="n">IS_RUNNING_PS_LINUX</span> <span class="k">else</span><span class="p">:</span> <span class="n">primary_resolver</span> <span class="o">=</span> <span class="n">IS_RUNNING_PS_LINUX</span> <span class="n">secondary_resolver</span> <span class="o">=</span> <span class="n">IS_RUNNING_PS_BSD</span> <span class="n">command_listing</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">primary_resolver</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">command_listing</span><span class="p">:</span> <span class="n">command_listing</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">secondary_resolver</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">command_listing</span><span class="p">:</span> <span class="n">command_listing</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">unicode</span><span class="o">.</span><span class="n">strip</span><span class="p">,</span> <span class="n">command_listing</span><span class="p">)</span> <span class="k">return</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">command_listing</span> <span class="k">return</span> <span class="bp">None</span> </div> <div class="viewcode-block" id="get_name_by_pid"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_name_by_pid">[docs]</a><span class="k">def</span> <span class="nf">get_name_by_pid</span><span class="p">(</span><span class="n">pid</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Attempts to determine the name a given process is running under (not</span> <span class="sd"> including arguments). This uses...</span> <span class="sd"> ::</span> <span class="sd"> 1. Information from /proc</span> <span class="sd"> 2. ps -p <pid> -o command</span> <span class="sd"> :param int pid: process id of the process to be queried</span> <span class="sd"> :returns: **str** with the process name, **None** if it can't be determined</span> <span class="sd"> """</span> <span class="n">process_name</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">is_available</span><span class="p">():</span> <span class="k">try</span><span class="p">:</span> <span class="n">process_name</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">get_stats</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">Stat</span><span class="o">.</span><span class="n">COMMAND</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># attempts to resolve using ps, failing if:</span> <span class="c"># - system's ps variant doesn't handle these flags (none known at the moment)</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ ps -p 5767 -o comm</span> <span class="c"># COMMAND</span> <span class="c"># vim</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">process_name</span><span class="p">:</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_NAME_BY_PID_PS</span> <span class="o">%</span> <span class="n">pid</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">'COMMAND'</span><span class="p">:</span> <span class="n">process_name</span> <span class="o">=</span> <span class="n">results</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">return</span> <span class="n">process_name</span> </div> <div class="viewcode-block" id="get_pid_by_name"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_pid_by_name">[docs]</a><span class="k">def</span> <span class="nf">get_pid_by_name</span><span class="p">(</span><span class="n">process_name</span><span class="p">,</span> <span class="n">multiple</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Attempts to determine the process id for a running process, using...</span> <span class="sd"> ::</span> <span class="sd"> 1. pgrep -x <name></span> <span class="sd"> 2. pidof <name></span> <span class="sd"> 3. ps -o pid -C <name> (linux)</span> <span class="sd"> ps axc | egrep " <name>$" (bsd)</span> <span class="sd"> 4. lsof -tc <name></span> <span class="sd"> :param str process_name: process name for which to fetch the pid</span> <span class="sd"> :param bool multiple: provides a list of all pids if **True**, otherwise</span> <span class="sd"> results with multiple processes are discarded</span> <span class="sd"> :returns:</span> <span class="sd"> Response depends upon the 'multiple' argument as follows...</span> <span class="sd"> * if **False** then this provides an **int** with the process id or **None** if it can't be determined</span> <span class="sd"> * if **True** then this provides a **list** of all **int** process ids, and an empty list if it can't be determined</span> <span class="sd"> """</span> <span class="c"># attempts to resolve using pgrep, failing if:</span> <span class="c"># - we're running on bsd (command unavailable)</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ pgrep -x vim</span> <span class="c"># 3283</span> <span class="c"># 3392</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"pgrep"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_NAME_PGREP</span> <span class="o">%</span> <span class="n">process_name</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">pids</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span> <span class="k">if</span> <span class="n">multiple</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">pids</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># attempts to resolve using pidof, failing if:</span> <span class="c"># - we're running on bsd (command unavailable)</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ pidof vim</span> <span class="c"># 3392 3283</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"pidof"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_NAME_PIDOF</span> <span class="o">%</span> <span class="n">process_name</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">pids</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">())</span> <span class="k">if</span> <span class="n">multiple</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">pids</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># attempts to resolve using ps, failing if:</span> <span class="c"># - system's ps variant doesn't handle these flags (none known at the moment)</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~/Desktop/stem$ ps -o pid -C vim</span> <span class="c"># PID</span> <span class="c"># 3283</span> <span class="c"># 3392</span> <span class="c">#</span> <span class="c"># atagar$ ps axc</span> <span class="c"># PID TT STAT TIME COMMAND</span> <span class="c"># 1 ?? Ss 9:00.22 launchd</span> <span class="c"># 10 ?? Ss 0:09.97 kextd</span> <span class="c"># 11 ?? Ss 5:47.36 DirectoryService</span> <span class="c"># 12 ?? Ss 3:01.44 notifyd</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"ps"</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">is_bsd</span><span class="p">():</span> <span class="c"># linux variant of ps</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_NAME_PS_LINUX</span> <span class="o">%</span> <span class="n">process_name</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">pids</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span> <span class="k">if</span> <span class="n">multiple</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">pids</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="n">is_bsd</span><span class="p">():</span> <span class="c"># bsd variant of ps</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_NAME_PS_BSD</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="c"># filters results to those with our process name</span> <span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span> <span class="k">if</span> <span class="n">r</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">" </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">process_name</span><span class="p">)]</span> <span class="k">try</span><span class="p">:</span> <span class="n">pids</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span> <span class="k">if</span> <span class="n">multiple</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">pids</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># resolves using lsof which works on both Linux and BSD, only failing if:</span> <span class="c"># - lsof is unavailable (not included by default on OpenBSD)</span> <span class="c"># - the process being run as a different user due to permissions</span> <span class="c"># - the process doesn't have any open files to be reported by lsof?</span> <span class="c">#</span> <span class="c"># flags:</span> <span class="c"># t - only show pids</span> <span class="c"># c - restrict results to that command</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ lsof -t -c vim</span> <span class="c"># 2470</span> <span class="c"># 2561</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"lsof"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_NAME_LSOF</span> <span class="o">%</span> <span class="n">process_name</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">pids</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span> <span class="k">if</span> <span class="n">multiple</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">pids</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">return</span> <span class="n">pids</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">pass</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"failed to resolve a pid for '</span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="n">process_name</span><span class="p">)</span> <span class="k">return</span> <span class="p">[]</span> <span class="k">if</span> <span class="n">multiple</span> <span class="k">else</span> <span class="bp">None</span> </div> <div class="viewcode-block" id="get_pid_by_port"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_pid_by_port">[docs]</a><span class="k">def</span> <span class="nf">get_pid_by_port</span><span class="p">(</span><span class="n">port</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Attempts to determine the process id for a process with the given port,</span> <span class="sd"> using...</span> <span class="sd"> ::</span> <span class="sd"> 1. netstat -npltu | grep 127.0.0.1:<port></span> <span class="sd"> 2. sockstat -4l -P tcp -p <port></span> <span class="sd"> 3. lsof -wnP -iTCP -sTCP:LISTEN | grep ":<port>"</span> <span class="sd"> Most queries limit results to listening TCP connections. This function likely</span> <span class="sd"> won't work on Mac OSX.</span> <span class="sd"> :param int port: port where the process we're looking for is listening</span> <span class="sd"> :returns: **int** with the process id, **None** if it can't be determined</span> <span class="sd"> """</span> <span class="c"># attempts to resolve using netstat, failing if:</span> <span class="c"># - netstat doesn't accept these flags (Linux only)</span> <span class="c"># - the process being run as a different user due to permissions</span> <span class="c">#</span> <span class="c"># flags:</span> <span class="c"># n - numeric (disables hostname lookups)</span> <span class="c"># p - program (include pids)</span> <span class="c"># l - listening (include listening sockets)</span> <span class="c"># tu - show tcp and udp sockets, and nothing else</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ netstat -npltu</span> <span class="c"># Active Internet connections (only servers)</span> <span class="c"># Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name</span> <span class="c"># tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN -</span> <span class="c"># tcp 0 0 127.0.0.1:9051 0.0.0.0:* LISTEN 1641/tor</span> <span class="c"># tcp6 0 0 ::1:631 :::* LISTEN -</span> <span class="c"># udp 0 0 0.0.0.0:5353 0.0.0.0:* -</span> <span class="c"># udp6 0 0 fe80::7ae4:ff:fe2f::123 :::* -</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"netstat"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_PORT_NETSTAT</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="c"># filters to results with our port</span> <span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span> <span class="k">if</span> <span class="s">"127.0.0.1:</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">port</span> <span class="ow">in</span> <span class="n">r</span><span class="p">]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">())</span> <span class="o">==</span> <span class="mi">7</span><span class="p">:</span> <span class="n">results</span> <span class="o">=</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">6</span><span class="p">]</span> <span class="c"># process field (ex. "7184/tor")</span> <span class="n">pid</span> <span class="o">=</span> <span class="n">results</span><span class="p">[:</span><span class="n">results</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">"/"</span><span class="p">)]</span> <span class="k">if</span> <span class="n">pid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span> <span class="c"># attempts to resolve using sockstat, failing if:</span> <span class="c"># - sockstat doesn't accept the -4 flag (BSD only)</span> <span class="c"># - sockstat isn't available (encountered with OSX 10.5.8)</span> <span class="c"># - there are multiple instances using the same port on different addresses</span> <span class="c">#</span> <span class="c"># flags:</span> <span class="c"># 4 - only show IPv4 sockets</span> <span class="c"># l - listening sockets</span> <span class="c"># P tcp - only show tcp connections</span> <span class="c"># p - only includes results if the local or foreign port match this</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># # sockstat -4 | grep tor</span> <span class="c"># _tor tor 4397 7 tcp4 51.64.7.84:9050 *:*</span> <span class="c"># _tor tor 4397 8 udp4 51.64.7.84:53 *:*</span> <span class="c"># _tor tor 4397 12 tcp4 51.64.7.84:54011 80.3.121.7:9001</span> <span class="c"># _tor tor 4397 15 tcp4 51.64.7.84:59374 7.42.1.102:9001</span> <span class="c"># _tor tor 4397 20 tcp4 51.64.7.84:51946 32.83.7.104:443</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"sockstat"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_PORT_SOCKSTAT</span> <span class="o">%</span> <span class="n">port</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="c"># filters to results where this is the local port</span> <span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span> <span class="k">if</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">split</span><span class="p">())</span> <span class="o">==</span> <span class="mi">7</span> <span class="ow">and</span> <span class="p">(</span><span class="s">":</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">port</span><span class="p">)</span> <span class="ow">in</span> <span class="n">r</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">5</span><span class="p">])]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">pid</span> <span class="o">=</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="n">pid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span> <span class="c"># resolves using lsof which works on both Linux and BSD, only failing if:</span> <span class="c"># - lsof is unavailable (not included by default on OpenBSD)</span> <span class="c"># - lsof doesn't provide the port ip/port, nor accept the -i and -s args</span> <span class="c"># (encountered with OSX 10.5.8)</span> <span class="c"># - the process being run as a different user due to permissions</span> <span class="c"># - there are multiple instances using the same port on different addresses</span> <span class="c">#</span> <span class="c"># flags:</span> <span class="c"># w - disables warning messages</span> <span class="c"># n - numeric addresses (disables hostname lookups)</span> <span class="c"># P - numeric ports (disables replacement of ports with their protocol)</span> <span class="c"># iTCP - only show tcp connections</span> <span class="c"># sTCP:LISTEN - listening sockets</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ lsof -wnP -iTCP -sTCP:LISTEN</span> <span class="c"># COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME</span> <span class="c"># tor 1745 atagar 6u IPv4 14229 0t0 TCP 127.0.0.1:9051 (LISTEN)</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"lsof"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_PORT_LSOF</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">results</span><span class="p">:</span> <span class="c"># filters to results with our port</span> <span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span> <span class="k">if</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">split</span><span class="p">())</span> <span class="o">==</span> <span class="mi">10</span> <span class="ow">and</span> <span class="p">(</span><span class="s">":</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">port</span><span class="p">)</span> <span class="ow">in</span> <span class="n">r</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">8</span><span class="p">])]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">pid</span> <span class="o">=</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">pid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span> <span class="k">return</span> <span class="bp">None</span> <span class="c"># all queries failed</span> </div> <div class="viewcode-block" id="get_pid_by_open_file"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_pid_by_open_file">[docs]</a><span class="k">def</span> <span class="nf">get_pid_by_open_file</span><span class="p">(</span><span class="n">path</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Attempts to determine the process id for a process with the given open file,</span> <span class="sd"> using...</span> <span class="sd"> ::</span> <span class="sd"> lsof -w <path></span> <span class="sd"> :param str path: location of the socket file to query against</span> <span class="sd"> :returns: **int** with the process id, **None** if it can't be determined</span> <span class="sd"> """</span> <span class="c"># resolves using lsof which works on both Linux and BSD, only failing if:</span> <span class="c"># - lsof is unavailable (not included by default on OpenBSD)</span> <span class="c"># - the file can't be read due to permissions</span> <span class="c">#</span> <span class="c"># flags:</span> <span class="c"># t - only show pids</span> <span class="c"># w - disables warning messages</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># atagar@morrigan:~$ lsof -tw /tmp/foo</span> <span class="c"># 4762</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"lsof"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_PID_BY_FILE_LSOF</span> <span class="o">%</span> <span class="n">path</span><span class="p">,</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">pid</span> <span class="o">=</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">if</span> <span class="n">pid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span> <span class="k">return</span> <span class="bp">None</span> <span class="c"># all queries failed</span> </div> <div class="viewcode-block" id="get_cwd"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_cwd">[docs]</a><span class="k">def</span> <span class="nf">get_cwd</span><span class="p">(</span><span class="n">pid</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Provides the working directory of the given process.</span> <span class="sd"> :param int pid: process id of the process to be queried</span> <span class="sd"> :returns: **str** with the absolute path for the process' present working</span> <span class="sd"> directory, **None** if it can't be determined</span> <span class="sd"> """</span> <span class="c"># try fetching via the proc contents if it's available</span> <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">is_available</span><span class="p">():</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">get_cwd</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span> <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># Fall back to a pwdx query. This isn't available on BSD.</span> <span class="n">logging_prefix</span> <span class="o">=</span> <span class="s">"get_cwd(</span><span class="si">%s</span><span class="s">):"</span> <span class="o">%</span> <span class="n">pid</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"pwdx"</span><span class="p">):</span> <span class="c"># pwdx results are of the form:</span> <span class="c"># 3799: /home/atagar</span> <span class="c"># 5839: No such process</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_CWD_PWDX</span> <span class="o">%</span> <span class="n">pid</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">results</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> pwdx didn't return any results"</span> <span class="o">%</span> <span class="n">logging_prefix</span><span class="p">)</span> <span class="k">elif</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">"No such process"</span><span class="p">):</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> pwdx processes reported for this pid"</span> <span class="o">%</span> <span class="n">logging_prefix</span><span class="p">)</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s">: "</span> <span class="o">%</span> <span class="n">pid</span><span class="p">):</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> we got unexpected output from pwdx: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">logging_prefix</span><span class="p">,</span> <span class="n">results</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="c"># Use lsof as the final fallback. This is available on both Linux and is the</span> <span class="c"># only lookup method here that works for BSD...</span> <span class="c"># https://trac.torproject.org/projects/tor/ticket/4236</span> <span class="c">#</span> <span class="c"># flags:</span> <span class="c"># a - presents the intersection of the following arguments</span> <span class="c"># p - limits results to this pid</span> <span class="c"># d cwd - limits results to just the cwd rather than all open files</span> <span class="c"># Fn - short listing in a single column, with just the pid and cwd</span> <span class="c">#</span> <span class="c"># example output:</span> <span class="c"># ~$ lsof -a -p 75717 -d cwd -Fn</span> <span class="c"># p75717</span> <span class="c"># n/Users/atagar/tor/src/or</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"lsof"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_CWD_LSOF</span> <span class="o">%</span> <span class="n">pid</span><span class="p">,</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">results</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"n/"</span><span class="p">):</span> <span class="n">lsof_result</span> <span class="o">=</span> <span class="n">results</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">:]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="c"># If we lack read permissions for the cwd then it returns...</span> <span class="c"># p2683</span> <span class="c"># n/proc/2683/cwd (readlink: Permission denied)</span> <span class="k">if</span> <span class="ow">not</span> <span class="s">" "</span> <span class="ow">in</span> <span class="n">lsof_result</span><span class="p">:</span> <span class="k">return</span> <span class="n">lsof_result</span> <span class="k">else</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> we got unexpected output from lsof: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">logging_prefix</span><span class="p">,</span> <span class="n">results</span><span class="p">))</span> <span class="k">return</span> <span class="bp">None</span> <span class="c"># all queries failed</span> </div> <div class="viewcode-block" id="get_user"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_user">[docs]</a><span class="k">def</span> <span class="nf">get_user</span><span class="p">(</span><span class="n">pid</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Provides the user a process is running under.</span> <span class="sd"> :param int pid: process id of the process to be queried</span> <span class="sd"> :returns: **str** with the username a process is running under, **None** if</span> <span class="sd"> it can't be determined</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span> <span class="ow">or</span> <span class="n">pid</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span> <span class="k">return</span> <span class="bp">None</span> <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">is_available</span><span class="p">():</span> <span class="k">try</span><span class="p">:</span> <span class="n">uid</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">get_uid</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span> <span class="k">if</span> <span class="n">uid</span> <span class="ow">and</span> <span class="n">uid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">return</span> <span class="n">pwd</span><span class="o">.</span><span class="n">getpwuid</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">uid</span><span class="p">))</span><span class="o">.</span><span class="n">pw_name</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="n">is_available</span><span class="p">(</span><span class="s">"ps"</span><span class="p">):</span> <span class="n">results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="s">"ps -o user </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">pid</span><span class="p">,</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">:</span> <span class="k">return</span> <span class="n">results</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">return</span> <span class="bp">None</span> </div> <div class="viewcode-block" id="get_start_time"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_start_time">[docs]</a><span class="k">def</span> <span class="nf">get_start_time</span><span class="p">(</span><span class="n">pid</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Provides the unix timestamp when the given process started.</span> <span class="sd"> :param int pid: process id of the process to be queried</span> <span class="sd"> :returns: **float** for the unix timestamp when the process began, **None**</span> <span class="sd"> if it can't be determined</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span> <span class="ow">or</span> <span class="n">pid</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span> <span class="k">return</span> <span class="bp">None</span> <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">is_available</span><span class="p">():</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="nb">float</span><span class="p">(</span><span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">get_stats</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">Stat</span><span class="o">.</span><span class="n">START_TIME</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span> <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span> <span class="k">pass</span> <span class="k">try</span><span class="p">:</span> <span class="n">ps_results</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="s">"ps -p </span><span class="si">%s</span><span class="s"> -o etime"</span> <span class="o">%</span> <span class="n">pid</span><span class="p">,</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">ps_results</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">:</span> <span class="n">etime</span> <span class="o">=</span> <span class="n">ps_results</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">parse_short_time_label</span><span class="p">(</span><span class="n">etime</span><span class="p">)</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">return</span> <span class="bp">None</span> </div> <div class="viewcode-block" id="get_bsd_jail_id"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_bsd_jail_id">[docs]</a><span class="k">def</span> <span class="nf">get_bsd_jail_id</span><span class="p">(</span><span class="n">pid</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Gets the jail id for a process. These seem to only exist for FreeBSD (this</span> <span class="sd"> style for jails does not exist on Linux, OSX, or OpenBSD).</span> <span class="sd"> :param int pid: process id of the jail id to be queried</span> <span class="sd"> :returns: **int** for the jail id, zero if this can't be determined</span> <span class="sd"> """</span> <span class="c"># Output when called from a FreeBSD jail or when Tor isn't jailed:</span> <span class="c"># JID</span> <span class="c"># 0</span> <span class="c">#</span> <span class="c"># Otherwise it's something like:</span> <span class="c"># JID</span> <span class="c"># 1</span> <span class="n">ps_output</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_BSD_JAIL_ID_PS</span> <span class="o">%</span> <span class="n">pid</span><span class="p">,</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">ps_output</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">ps_output</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">())</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">jid</span> <span class="o">=</span> <span class="n">ps_output</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">if</span> <span class="n">jid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">jid</span><span class="p">)</span> <span class="n">os_name</span> <span class="o">=</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="k">if</span> <span class="n">os_name</span> <span class="o">==</span> <span class="s">"FreeBSD"</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">"Unable to get the jail id for process </span><span class="si">%s</span><span class="s">."</span> <span class="o">%</span> <span class="n">pid</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"get_bsd_jail_id(</span><span class="si">%s</span><span class="s">): jail ids do not exist on </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">os_name</span><span class="p">))</span> <span class="k">return</span> <span class="mi">0</span> </div> <div class="viewcode-block" id="get_bsd_jail_path"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_bsd_jail_path">[docs]</a><span class="k">def</span> <span class="nf">get_bsd_jail_path</span><span class="p">(</span><span class="n">jid</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Provides the path of the given FreeBSD jail.</span> <span class="sd"> :param int jid: jail id to be queried</span> <span class="sd"> :returns: **str** of the path prefix, **None** if this can't be determined</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">jid</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span> <span class="c"># Output should be something like:</span> <span class="c"># JID IP Address Hostname Path</span> <span class="c"># 1 10.0.0.2 tor-jail /usr/jails/tor-jail</span> <span class="n">jls_output</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="n">GET_BSD_JAIL_PATH</span> <span class="o">%</span> <span class="n">jid</span><span class="p">,</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">jls_output</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">jls_output</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">())</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span> <span class="k">return</span> <span class="n">jls_output</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">3</span><span class="p">]</span> <span class="k">return</span> <span class="bp">None</span> </div> <div class="viewcode-block" id="expand_path"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.expand_path">[docs]</a><span class="k">def</span> <span class="nf">expand_path</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">cwd</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Provides an absolute path, expanding tildes with the user's home and</span> <span class="sd"> appending a current working directory if the path was relative.</span> <span class="sd"> :param str path: path to be expanded</span> <span class="sd"> :param str cwd: current working directory to expand relative paths with, our</span> <span class="sd"> process' if this is **None**</span> <span class="sd"> :returns: **str** of the path expanded to be an absolute path, never with an</span> <span class="sd"> ending slash</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">is_windows</span><span class="p">():</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="s">"</span><span class="se">\\</span><span class="s">"</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s">"</span><span class="se">\\</span><span class="s">"</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s">"/"</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">relative_path</span> <span class="ow">or</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isabs</span><span class="p">(</span><span class="n">relative_path</span><span class="p">):</span> <span class="c"># empty or already absolute - nothing to do</span> <span class="k">pass</span> <span class="k">elif</span> <span class="n">relative_path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"~"</span><span class="p">):</span> <span class="c"># prefixed with a ~ or ~user entry</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="n">relative_path</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c"># relative path, expand with the cwd</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">cwd</span><span class="p">:</span> <span class="n">cwd</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getcwd</span><span class="p">()</span> <span class="c"># we'll be dealing with both "my/path/" and "./my/path" entries, so</span> <span class="c"># cropping the later</span> <span class="k">if</span> <span class="n">relative_path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"./"</span><span class="p">)</span> <span class="ow">or</span> <span class="n">relative_path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">".</span><span class="se">\\</span><span class="s">"</span><span class="p">):</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="n">relative_path</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span> <span class="k">elif</span> <span class="n">relative_path</span> <span class="o">==</span> <span class="s">"."</span><span class="p">:</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="s">""</span> <span class="k">if</span> <span class="n">relative_path</span> <span class="o">==</span> <span class="s">""</span><span class="p">:</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="n">cwd</span> <span class="k">else</span><span class="p">:</span> <span class="n">relative_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cwd</span><span class="p">,</span> <span class="n">relative_path</span><span class="p">)</span> <span class="k">return</span> <span class="n">relative_path</span> </div> <div class="viewcode-block" id="call"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.call">[docs]</a><span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">,</span> <span class="n">ignore_exit_status</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Issues a command in a subprocess, blocking until completion and returning the</span> <span class="sd"> results. This is not actually ran in a shell so pipes and other shell syntax</span> <span class="sd"> are not permitted.</span> <span class="sd"> :param str command: command to be issued</span> <span class="sd"> :param object default: response if the query fails</span> <span class="sd"> :param bool ignore_exit_status: reports failure if our command's exit status</span> <span class="sd"> was non-zero</span> <span class="sd"> :returns: **list** with the lines of output from the command</span> <span class="sd"> :raises: **OSError** if this fails and no default was provided</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">is_shell_command</span> <span class="o">=</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">SHELL_COMMANDS</span> <span class="n">start_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">shell</span> <span class="o">=</span> <span class="n">is_shell_command</span><span class="p">)</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">communicate</span><span class="p">()</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span> <span class="o">=</span> <span class="n">stdout</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">stderr</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="n">runtime</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start_time</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"System call: </span><span class="si">%s</span><span class="s"> (runtime: </span><span class="si">%0.2f</span><span class="s">)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">runtime</span><span class="p">))</span> <span class="n">trace_prefix</span> <span class="o">=</span> <span class="s">"Received from system (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">command</span> <span class="k">if</span> <span class="n">stdout</span> <span class="ow">and</span> <span class="n">stderr</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">trace</span><span class="p">(</span><span class="n">trace_prefix</span> <span class="o">+</span> <span class="s">", stdout:</span><span class="se">\n</span><span class="si">%s</span><span class="se">\n</span><span class="s">stderr:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">))</span> <span class="k">elif</span> <span class="n">stdout</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">trace</span><span class="p">(</span><span class="n">trace_prefix</span> <span class="o">+</span> <span class="s">", stdout:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">stdout</span><span class="p">)</span> <span class="k">elif</span> <span class="n">stderr</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">trace</span><span class="p">(</span><span class="n">trace_prefix</span> <span class="o">+</span> <span class="s">", stderr:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">stderr</span><span class="p">)</span> <span class="n">exit_code</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">poll</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">ignore_exit_status</span> <span class="ow">and</span> <span class="n">exit_code</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="s">"</span><span class="si">%s</span><span class="s"> returned exit status </span><span class="si">%i</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">exit_code</span><span class="p">))</span> <span class="k">if</span> <span class="n">stdout</span><span class="p">:</span> <span class="k">return</span> <span class="n">stdout</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">,</span> <span class="s">"replace"</span><span class="p">)</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="p">[]</span> <span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"System call (failed): </span><span class="si">%s</span><span class="s"> (error: </span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">exc</span><span class="p">))</span> <span class="k">if</span> <span class="n">default</span> <span class="o">!=</span> <span class="n">UNDEFINED</span><span class="p">:</span> <span class="k">return</span> <span class="n">default</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> </div> <div class="viewcode-block" id="get_process_name"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.get_process_name">[docs]</a><span class="k">def</span> <span class="nf">get_process_name</span><span class="p">():</span> <span class="sd">"""</span> <span class="sd"> Provides the present name of our process.</span> <span class="sd"> :returns: **str** with the present name of our process</span> <span class="sd"> """</span> <span class="k">global</span> <span class="n">_PROCESS_NAME</span><span class="p">,</span> <span class="n">_MAX_NAME_LENGTH</span> <span class="k">if</span> <span class="n">_PROCESS_NAME</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="c"># Example output...</span> <span class="c">#</span> <span class="c"># COMMAND</span> <span class="c"># python run_tests.py --unit</span> <span class="n">ps_output</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="s">"ps -p </span><span class="si">%i</span><span class="s"> -o args"</span> <span class="o">%</span> <span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">(),</span> <span class="p">[])</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">ps_output</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">ps_output</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"COMMAND"</span><span class="p">,</span> <span class="s">"ARGS"</span><span class="p">):</span> <span class="n">_PROCESS_NAME</span> <span class="o">=</span> <span class="n">ps_output</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="c"># Falling back on using ctypes to get our argv. Unfortunately the simple</span> <span class="c"># method for getting this...</span> <span class="c">#</span> <span class="c"># " ".join(["python"] + sys.argv)</span> <span class="c">#</span> <span class="c"># ... doesn't do the trick since this will miss interpretor arguments.</span> <span class="c">#</span> <span class="c"># python -W ignore::DeprecationWarning my_script.py</span> <span class="n">args</span><span class="p">,</span> <span class="n">argc</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">argc_t</span><span class="p">()</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="c"># The ending index can be either None or raise a ValueError when</span> <span class="c"># accessed...</span> <span class="c">#</span> <span class="c"># ValueError: NULL pointer access</span> <span class="k">try</span><span class="p">:</span> <span class="k">if</span> <span class="n">argc</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">break</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">break</span> <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">argc</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span> <span class="n">_PROCESS_NAME</span> <span class="o">=</span> <span class="s">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="n">_MAX_NAME_LENGTH</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">_PROCESS_NAME</span><span class="p">)</span> <span class="k">return</span> <span class="n">_PROCESS_NAME</span> </div> <div class="viewcode-block" id="set_process_name"><a class="viewcode-back" href="../../../api/util/system.html#stem.util.system.set_process_name">[docs]</a><span class="k">def</span> <span class="nf">set_process_name</span><span class="p">(</span><span class="n">process_name</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Renames our current process from "python <args>" to a custom name. This is</span> <span class="sd"> best-effort, not necessarily working on all platforms.</span> <span class="sd"> :param str process_name: new name for our process</span> <span class="sd"> """</span> <span class="c"># This is mostly based on...</span> <span class="c">#</span> <span class="c"># http://www.rhinocerus.net/forum/lang-python/569677-setting-program-name-like-0-perl.html#post2272369</span> <span class="c">#</span> <span class="c"># ... and an adaptation by Jake...</span> <span class="c">#</span> <span class="c"># https://github.com/ioerror/chameleon</span> <span class="c">#</span> <span class="c"># A cleaner implementation is available at...</span> <span class="c">#</span> <span class="c"># https://github.com/cream/libs/blob/b38970e2a6f6d2620724c828808235be0445b799/cream/util/procname.py</span> <span class="c">#</span> <span class="c"># but I'm not quite clear on their implementation, and it only does targeted</span> <span class="c"># argument replacement (ie, replace argv[0], argv[1], etc but with a string</span> <span class="c"># the same size).</span> <span class="n">_set_argv</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> <span class="k">if</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">==</span> <span class="s">"Linux"</span><span class="p">:</span> <span class="n">_set_prctl_name</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> <span class="k">elif</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"Darwin"</span><span class="p">,</span> <span class="s">"FreeBSD"</span><span class="p">,</span> <span class="s">"OpenBSD"</span><span class="p">):</span> <span class="n">_set_proc_title</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> </div> <span class="k">def</span> <span class="nf">_set_argv</span><span class="p">(</span><span class="n">process_name</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Overwrites our argv in a similar fashion to how it's done in C with:</span> <span class="sd"> strcpy(argv[0], "new_name");</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">Py_GetArgcArgv</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="k">global</span> <span class="n">_PROCESS_NAME</span> <span class="c"># both gets the current process name and initializes _MAX_NAME_LENGTH</span> <span class="n">current_name</span> <span class="o">=</span> <span class="n">get_process_name</span><span class="p">()</span> <span class="n">argv</span><span class="p">,</span> <span class="n">argc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">argc_t</span><span class="p">()</span> <span class="n">Py_GetArgcArgv</span><span class="p">(</span><span class="n">argv</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">pointer</span><span class="p">(</span><span class="n">argc</span><span class="p">))</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> <span class="o">></span> <span class="n">_MAX_NAME_LENGTH</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">"Can't rename process to something longer than our initial name (this would overwrite memory used for the env)"</span><span class="p">)</span> <span class="c"># space we need to clear</span> <span class="n">zero_size</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">current_name</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">process_name</span><span class="p">))</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">memset</span><span class="p">(</span><span class="n">argc</span><span class="o">.</span><span class="n">contents</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">zero_size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="c"># null terminate the string's end</span> <span class="n">process_name_encoded</span> <span class="o">=</span> <span class="n">process_name</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf8'</span><span class="p">)</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">memmove</span><span class="p">(</span><span class="n">argc</span><span class="o">.</span><span class="n">contents</span><span class="p">,</span> <span class="n">process_name_encoded</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">process_name</span><span class="p">))</span> <span class="n">_PROCESS_NAME</span> <span class="o">=</span> <span class="n">process_name</span> <span class="k">def</span> <span class="nf">_set_prctl_name</span><span class="p">(</span><span class="n">process_name</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Sets the prctl name, which is used by top and killall. This appears to be</span> <span class="sd"> Linux specific and has the max of 15 characters.</span> <span class="sd"> This is from...</span> <span class="sd"> http://stackoverflow.com/questions/564695/is-there-a-way-to-change-effective-process-name-in-python/923034#923034</span> <span class="sd"> """</span> <span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s">"c"</span><span class="p">))</span> <span class="n">name_buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="n">name_buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_bytes</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> <span class="n">libc</span><span class="o">.</span><span class="n">prctl</span><span class="p">(</span><span class="n">PR_SET_NAME</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">name_buffer</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_set_proc_title</span><span class="p">(</span><span class="n">process_name</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> BSD specific calls (should be compataible with both FreeBSD and OpenBSD:</span> <span class="sd"> http://fxr.watson.org/fxr/source/gen/setproctitle.c?v=FREEBSD-LIBC</span> <span class="sd"> http://www.rootr.net/man/man/setproctitle/3</span> <span class="sd"> """</span> <span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s">"c"</span><span class="p">))</span> <span class="n">name_buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">process_name</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="n">name_buffer</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">process_name</span> <span class="k">try</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">setproctitle</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">name_buffer</span><span class="p">))</span> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span> <span class="c"># Possible issue (seen on OSX):</span> <span class="c"># AttributeError: dlsym(0x7fff6a41d1e0, setproctitle): symbol not found</span> <span class="k">pass</span> </pre></div> </div> <div class="bottomnav"> </div> <div class="footer"> </div> </body> </html>