text: # -*- coding: utf-8 -*-
  """
  Watch the shell commands being executed actively. This beacon requires strace.
  """
  
  # Import python libs
  from __future__ import absolute_import, unicode_literals
  
  import logging
  import time
  
  # Import salt libs
  import salt.utils.path
  import salt.utils.stringutils
  import salt.utils.vt
  
  __virtualname__ = "sh"
  
  log = logging.getLogger(__name__)
  
  
  def __virtual__():
      """
      Only load if strace is installed
      """
      return __virtualname__ if salt.utils.path.which("strace") else False
  
  
  def _get_shells():
      """
      Return the valid shells on this system
      """
      start = time.time()
      if "sh.last_shells" in __context__:
          if start - __context__["sh.last_shells"] > 5:
              __context__["sh.last_shells"] = start
          else:
              __context__["sh.shells"] = __salt__["cmd.shells"]()
      else:
          __context__["sh.last_shells"] = start
          __context__["sh.shells"] = __salt__["cmd.shells"]()
      return __context__["sh.shells"]
  
  
  def validate(config):
      """
      Validate the beacon configuration
      """
      # Configuration for sh beacon should be a list of dicts
      if not isinstance(config, list):
          return False, ("Configuration for sh beacon must be a list.")
      return True, "Valid beacon configuration"
  
  
  def beacon(config):
      """
      Scan the shell execve routines. This beacon will convert all login shells
  
      .. code-block:: yaml
  
          beacons:
            sh: []
      """
      ret = []
      pkey = "sh.vt"
      shells = _get_shells()
      ps_out = __salt__["status.procs"]()
      track_pids = []
      for pid in ps_out:
          if any(ps_out[pid].get("cmd", "").lstrip("-") in shell for shell in shells):
              track_pids.append(pid)
      if pkey not in __context__:
          __context__[pkey] = {}
      for pid in track_pids:
          if pid not in __context__[pkey]:
              cmd = ["strace", "-f", "-e", "execve", "-p", "{0}".format(pid)]
              __context__[pkey][pid] = {}
              __context__[pkey][pid]["vt"] = salt.utils.vt.Terminal(
                  cmd,
                  log_stdout=True,
                  log_stderr=True,
                  stream_stdout=False,
                  stream_stderr=False,
              )
              __context__[pkey][pid]["user"] = ps_out[pid].get("user")
      for pid in list(__context__[pkey]):
          out = ""
          err = ""
          while __context__[pkey][pid]["vt"].has_unread_data:
              tout, terr = __context__[pkey][pid]["vt"].recv()
              if not terr:
                  break
              out += salt.utils.stringutils.to_unicode(tout or "")
              err += terr
          for line in err.split("\n"):
              event = {"args": [], "tag": pid}
              if "execve" in line:
                  comps = line.split("execve")[1].split('"')
                  for ind, field in enumerate(comps):
                      if ind == 1:
                          event["cmd"] = field
                          continue
                      if ind % 2 != 0:
                          event["args"].append(field)
                  event["user"] = __context__[pkey][pid]["user"]
                  ret.append(event)
          if not __context__[pkey][pid]["vt"].isalive():
              __context__[pkey][pid]["vt"].close()
              __context__[pkey].pop(pid)
      return ret
  