code: def run_shell(cmd, timeout=60, verbose=False):
      
      retcode = None
      try:
          p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, executable='/bin/bash')
          continue_running = True
      except Exception as e:
          yield("Failed: %s" % e)
          continue_running = False
  
      while continue_running:
          try:
              line = p.stdout.readline()
              if verbose and line:
                  yield(line)
              elif line.strip():
                  yield(line.strip())
          except Exception:
              pass
  
          try:
              data = irc.recv(4096)
          except Exception as e:
              data = ""
              retcode = p.poll()  # returns None while subprocess is running
  
          if '!cancel' in data:
              retcode = "Cancelled live output reading. You have to kill the process manually."
              yield "[X]: %s" % retcode
              break
  
          elif retcode is not None:
              try:
                  line = p.stdout.read()
              except:
                  retcode = "Too much output, read timed out. Process is still running in background."
  
              if verbose and line:
                  yield line
  
              if retcode != 0:
                  yield "[X]: %s" % retcode
              elif retcode == 0 and verbose:
                  yield "[√]"
  
              break
docs: run a shell command and return the output, verbose enables live command output via yield