docs: def run(self):
          '''
          Execute the salt command line
          '''
          import salt.client
          self.parse_args()
  
          if self.config['log_level'] not in ('quiet', ):
              # Setup file logging!
              self.setup_logfile_logger()
              verify_log(self.config)
  
          try:
              # We don't need to bail on config file permission errors
              # if the CLI process is run with the -a flag
              skip_perm_errors = self.options.eauth != ''
  
              self.local_client = salt.client.get_local_client(
                  self.get_config_file_path(),
                  skip_perm_errors=skip_perm_errors,
                  auto_reconnect=True)
          except SaltClientError as exc:
              self.exit(2, '{0}\n'.format(exc))
              return
  
          if self.options.batch or self.options.static:
              # _run_batch() will handle all output and
              # exit with the appropriate error condition
              # Execution will not continue past this point
              # in batch mode.
              self._run_batch()
              return
  
          if self.options.preview_target:
              minion_list = self._preview_target()
              self._output_ret(minion_list, self.config.get('output', 'nested'))
              return
  
          if self.options.timeout <= 0:
              self.options.timeout = self.local_client.opts['timeout']
  
          kwargs = {
              'tgt': self.config['tgt'],
              'fun': self.config['fun'],
              'arg': self.config['arg'],
              'timeout': self.options.timeout,
              'show_timeout': self.options.show_timeout,
              'show_jid': self.options.show_jid}
  
          if 'token' in self.config:
              import salt.utils.files
              try:
                  with salt.utils.files.fopen(os.path.join(self.config['cachedir'], '.root_key'), 'r') as fp_:
                      kwargs['key'] = fp_.readline()
              except IOError:
                  kwargs['token'] = self.config['token']
  
          kwargs['delimiter'] = self.options.delimiter
  
          if self.selected_target_option:
              kwargs['tgt_type'] = self.selected_target_option
          else:
              kwargs['tgt_type'] = 'glob'
  
          # If batch_safe_limit is set, check minions matching target and
          # potentially switch to batch execution
          if self.options.batch_safe_limit > 1:
              if len(self._preview_target()) >= self.options.batch_safe_limit:
                  salt.utils.stringutils.print_cli('\nNOTICE: Too many minions targeted, switching to batch execution.')
                  self.options.batch = self.options.batch_safe_size
                  self._run_batch()
                  return
  
          if getattr(self.options, 'return'):
              kwargs['ret'] = getattr(self.options, 'return')
  
          if getattr(self.options, 'return_config'):
              kwargs['ret_config'] = getattr(self.options, 'return_config')
  
          if getattr(self.options, 'return_kwargs'):
              kwargs['ret_kwargs'] = yamlify_arg(
                      getattr(self.options, 'return_kwargs'))
  
          if getattr(self.options, 'module_executors'):
              kwargs['module_executors'] = yamlify_arg(getattr(self.options, 'module_executors'))
  
          if getattr(self.options, 'executor_opts'):
              kwargs['executor_opts'] = yamlify_arg(getattr(self.options, 'executor_opts'))
  
          if getattr(self.options, 'metadata'):
              kwargs['metadata'] = yamlify_arg(
                      getattr(self.options, 'metadata'))
  
          # If using eauth and a token hasn't already been loaded into
          # kwargs, prompt the user to enter auth credentials
          if 'token' not in kwargs and 'key' not in kwargs and self.options.eauth:
              # This is expensive. Don't do it unless we need to.
              import salt.auth
              resolver = salt.auth.Resolver(self.config)
              res = resolver.cli(self.options.eauth)
              if self.options.mktoken and res:
                  tok = resolver.token_cli(
                          self.options.eauth,
                          res
                          )
                  if tok:
                      kwargs['token'] = tok.get('token', '')
              if not res:
                  sys.stderr.write('ERROR: Authentication failed\n')
                  sys.exit(2)
              kwargs.update(res)
              kwargs['eauth'] = self.options.eauth
  
          if self.config['async']:
              jid = self.local_client.cmd_async(**kwargs)
              salt.utils.stringutils.print_cli('Executed command with job ID: {0}'.format(jid))
              return
  
          # local will be None when there was an error
          if not self.local_client:
              return
  
          retcodes = []
          errors = []
  
          try:
              if self.options.subset:
                  cmd_func = self.local_client.cmd_subset
                  kwargs['sub'] = self.options.subset
                  kwargs['cli'] = True
              else:
                  cmd_func = self.local_client.cmd_cli
  
              if self.options.progress:
                  kwargs['progress'] = True
                  self.config['progress'] = True
                  ret = {}
                  for progress in cmd_func(**kwargs):
                      out = 'progress'
                      try:
                          self._progress_ret(progress, out)
                      except LoaderError as exc:
                          raise SaltSystemExit(exc)
                      if 'return_count' not in progress:
                          ret.update(progress)
                  self._progress_end(out)
                  self._print_returns_summary(ret)
              elif self.config['fun'] == 'sys.doc':
                  ret = {}
                  out = ''
                  for full_ret in self.local_client.cmd_cli(**kwargs):
                      ret_, out, retcode = self._format_ret(full_ret)
                      ret.update(ret_)
                  self._output_ret(ret, out, retcode=retcode)
              else:
                  if self.options.verbose:
                      kwargs['verbose'] = True
                  ret = {}
                  for full_ret in cmd_func(**kwargs):
                      try:
                          ret_, out, retcode = self._format_ret(full_ret)
                          retcodes.append(retcode)
                          self._output_ret(ret_, out, retcode=retcode)
                          ret.update(full_ret)
                      except KeyError:
                          errors.append(full_ret)
  
              # Returns summary
              if self.config['cli_summary'] is True:
                  if self.config['fun'] != 'sys.doc':
                      if self.options.output is None:
                          self._print_returns_summary(ret)
                          self._print_errors_summary(errors)
  
              # NOTE: Return code is set here based on if all minions
              # returned 'ok' with a retcode of 0.
              # This is the final point before the 'salt' cmd returns,
              # which is why we set the retcode here.
              if not all(exit_code == salt.defaults.exitcodes.EX_OK for exit_code in retcodes):
                  sys.stderr.write('ERROR: Minions returned with non-zero exit code\n')
                  sys.exit(salt.defaults.exitcodes.EX_GENERIC)
  
          except (AuthenticationError,
                  AuthorizationError,
                  SaltInvocationError,
                  EauthAuthenticationError,
                  SaltClientError) as exc:
              ret = six.text_type(exc)
              self._output_ret(ret, '', retcode=1)