docs: def execute(command, return_output=True, log_file=None, log_settings=None, error_logfile=None, timeout=None, line_function=None, poll_timing = 0.01, logger=None, working_folder=None, env=None):
      """
          Execute a program and logs standard output into a file.
  
          :param return_output:      returns the STDOUT value if True or returns the return code
          :param logfile:            path where log file should be written ( displayed on STDOUT if not set)
          :param error_logfile:      path where error log file should be written ( displayed on STDERR if not set)
          :param timeout:            if set, it will kill the subprocess created when "timeout" seconds is reached. It will then raise an Exception.
          :param line_function:      set it to a "function pointer" for the function to be called each time a new line is written (line passed as a parameter).
          :param poll_timing:        wait time between timeout checks and std output check.
  
          :returns:   Standard output of the command or if return_output=False, it will give the "return code" of the command
      """
  
      tmp_log = False
      if log_settings:
          log_folder = log_settings.get('LOG_FOLDER')
      else:
          tmp_log = True
          log_folder = tempfile.mkdtemp()
  
      if not log_file:
          log_file = os.path.join(log_folder, "commands", "execute-command-logfile-%s.log" % UUID.uuid4())
          try:
              if not os.path.isdir(os.path.join(log_folder, "commands")):
                  os.makedirs(os.path.join(log_folder, "commands"))
          except:
              pass
      if not logger:
          logger = logging.getLogger('command_execute')
  
      logfile_writer = open(log_file, 'a')
      header = "%s - Executing command (timeout=%s) :\n\t%s\n\n\n" % (datetime.now().isoformat(), timeout, command)
      logfile_writer.write(header)
      logfile_writer.flush()
  
      logfile_reader = open(log_file, 'rb')
      logfile_reader.seek(0, os.SEEK_END)
      logfile_start_position = logfile_reader.tell()
  
      if error_logfile:
          err_logfile_writer = open(error_logfile, 'a')
      else:
          err_logfile_writer = logfile_writer
  
      start = datetime.now()
      timeout_string = ""
      if timeout:
          timeout_string = "(timeout=%s)" % timeout
      logger.info(u"Executing command %s :\n\t\t%s" % (timeout_string, command) )
  
      # We use "exec <command>" as Popen launches a shell, that runs the command.
      # It will transform the child process "sh" into the "command exectable" because of the "exec".
      # Said more accuratly, it won't fork to create launch the command in a sub sub process.
      # Therefore, when you kill the child process, you kill the "command" process and not the unecessary "sh" parent process.
      if sys.platform != 'win32':
          command = u"exec %s" % text_utils.uni(command)
      process = subprocess.Popen(command, stdout=logfile_writer, stderr=err_logfile_writer, bufsize=1, shell=True, cwd=working_folder, env=env)
  
      while process.poll() == None:
          # In order to avoid unecessary cpu usage, we wait for "poll_timing" seconds ( default: 0.1 sec )
          time.sleep(poll_timing)
  
          # Timeout check
          if timeout != None:
              now = datetime.now()
              if (now - start).seconds> timeout:
                  #process.terminate() ??
                  os.kill(process.pid, signal.SIGKILL)
                  os.waitpid(-1, os.WNOHANG)
                  raise Exception("Command execution timed out (took more than %s seconds...)" % timeout)
  
          # Line function call:
          #   => if line_function is defined, we call it on each new line of the file.
          if line_function:
              o = text_utils.uni(logfile_reader.readline()).rstrip()
              while o != '':
                  line_function(o)
                  o = text_utils.uni(logfile_reader.readline()).rstrip()
  
      if not return_output:
          # Return result code and ensure we have waited for the end of sub process
          return process.wait()
  
      logfile_reader.seek(logfile_start_position, os.SEEK_SET) #back to the beginning of the file
  
      res = text_utils.uni(logfile_reader.read())
  
      try:
          logfile_reader.close()
          logfile_writer.close()
          err_logfile_writer.close()
  
          if tmp_log:
              shutil.rmtree(log_folder, ignore_errors=True)
      except:
          logger.exception("Error while cleaning after tbx.execute() call.")
  
      return res