docs: def send(self, sendspec):
  		"""Send string as a shell command, and wait until the expected output
  		is seen (either a string or any from a list of strings) before
  		returning. The expected string will default to the currently-set
  		default expected string (see get_default_shutit_pexpect_session_expect)
  
  		Returns the pexpect return value (ie which expected string in the list
  		matched)
  
  		@return:                     The pexpect return value (ie which expected
  		                             string in the list matched).
  		                             If return is -1, the task was backgrounded. See also multisend.
  		@rtype:                      int
  		"""
  		shutit = self.shutit
  		shutit.log('In session: ' + self.pexpect_session_id + ', trying to send: ' + str(sendspec.send), level=logging.DEBUG)
  		if self._check_blocked(sendspec):
  			shutit.log('In send for ' + str(sendspec.send) + ', check_blocked called and returned True.', level=logging.DEBUG)
  			# _check_blocked will add to the list of background tasks and handle dupes, so leave there.
  			return -1
  		shutit = self.shutit
  		cfg = shutit.cfg
  		# Set up what we expect.
  		sendspec.expect = sendspec.expect or self.default_expect
  		assert sendspec.send is not None, shutit_util.print_debug()
  		if sendspec.send.strip() == '':
  			sendspec.fail_on_empty_before=False
  			sendspec.check_exit=False
  		if isinstance(sendspec.expect, dict):
  			return self.multisend(ShutItSendSpec(self,
  			                                     send=sendspec.send,
  			                                     send_dict=sendspec.expect,
  			                                     expect=shutit.get_default_shutit_pexpect_session_expect(),
  			                                     timeout=sendspec.timeout,
  			                                     check_exit=sendspec.check_exit,
  			                                     fail_on_empty_before=sendspec.fail_on_empty_before,
  			                                     record_command=sendspec.record_command,
  			                                     exit_values=sendspec.exit_values,
  			                                     echo=sendspec.echo,
  			                                     note=sendspec.note,
  			                                     secret=sendspec.secret,
  			                                     check_sudo=sendspec.check_sudo,
  			                                     nonewline=sendspec.nonewline,
  			                                     loglevel=sendspec.loglevel))
  
  		# Before gathering expect, detect whether this is a sudo command and act accordingly.
  		command_list = sendspec.send.strip().split()
  		# If there is a first command, there is a sudo in there (we ignore
  		# whether it's quoted in the command), and we do not have sudo rights
  		# cached...
  		# TODO: check for sudo in pipelines, eg 'cmd | sudo' or 'cmd |sudo' but not 'echo " sudo "'
  		if sendspec.check_sudo and command_list and command_list[0] == 'sudo' and not self.check_sudo():
  			sudo_pass = self.get_sudo_pass_if_needed(shutit)
  			# Turn expect into a dict.
  			return self.multisend(ShutItSendSpec(self,
  			                                     send=sendspec.send,
  			                                     send_dict={'assword':[sudo_pass, True]},
  			                                     expect=shutit.get_default_shutit_pexpect_session_expect(),
  			                                     timeout=sendspec.timeout,
  			                                     check_exit=sendspec.check_exit,
  			                                     fail_on_empty_before=sendspec.fail_on_empty_before,
  			                                     record_command=sendspec.record_command,
  			                                     exit_values=sendspec.exit_values,
  			                                     echo=sendspec.echo,
  			                                     note=sendspec.note,
  			                                     check_sudo=False,
  			                                     nonewline=sendspec.nonewline,
  			                                     loglevel=sendspec.loglevel))
  
  		shutit.handle_note(sendspec.note, command=str(sendspec.send), training_input=str(sendspec.send))
  		if sendspec.timeout is None:
  			sendspec.timeout = 3600
  
  		sendspec.echo = shutit.get_echo_override(sendspec.echo)
  
  		# Handle OSX to get the GNU version of the command
  		if sendspec.assume_gnu:
  			sendspec.send = shutit.get_send_command(sendspec.send)
  
  		# If check_exit is not passed in
  		# - if the expect matches the default, use the default check exit
  		# - otherwise, default to doing the check
  		if sendspec.check_exit is None:
  			# If we are in video mode, ignore exit value
  			if (shutit.build['video'] != -1 or shutit.build['video'] is True) or shutit.build['training'] or shutit.build['walkthrough'] or shutit.build['exam']:
  				sendspec.check_exit = False
  			elif sendspec.expect == shutit.get_default_shutit_pexpect_session_expect():
  				sendspec.check_exit = shutit.get_default_shutit_pexpect_session_check_exit()
  			else:
  				# If expect given doesn't match the defaults and no argument
  				# was passed in (ie check_exit was passed in as None), set
  				# check_exit to true iff it matches a prompt.
  				expect_matches_prompt = False
  				for prompt in shutit.expect_prompts:
  					if prompt == sendspec.expect:
  						expect_matches_prompt = True
  				if not expect_matches_prompt:
  					sendspec.check_exit = False
  				else:
  					sendspec.check_exit = True
  
  		# Determine whether we record this command.
  		ok_to_record = False
  		if not sendspec.echo and sendspec.record_command is None:
  			sendspec.record_command = False
  		if sendspec.record_command is None or sendspec.record_command:
  			ok_to_record = True
  			for i in cfg.keys():
  				if isinstance(cfg[i], dict):
  					for j in cfg[i].keys():
  						if (j == 'password' or j == 'passphrase') and cfg[i][j] == sendspec.send:
  							shutit.build['shutit_command_history'].append ('#redacted command, password')
  							ok_to_record = False
  							break
  				if not ok_to_record or sendspec.send in shutit_global.shutit_global_object.secret_words_set:
  					sendspec.secret = True
  					break
  			if ok_to_record:
  				shutit.build['shutit_command_history'].append(sendspec.send)
  
  		# Log - tho not if secret.
  		if sendspec.send != None:
  			shutit.log('================================================================================', level=logging.DEBUG)
  			send_and_expect_summary_msg = ''
  			if not sendspec.echo and not sendspec.secret:
  				send_and_expect_summary_msg += 'Sending: ' + sendspec.send
  			elif not sendspec.echo and sendspec.secret:
  				send_and_expect_summary_msg += 'Sending: ' + sendspec.send
  			if not sendspec.secret:
  				send_and_expect_summary_msg += 'Sending>>>' + sendspec.send + '<<<'
  			else:
  				send_and_expect_summary_msg += 'Sending>>>[SECRET]<<<'
  			send_and_expect_summary_msg += ', expecting>>>' + str(sendspec.expect) + '<<<'
  			shutit.log(send_and_expect_summary_msg, level=logging.DEBUG)
  
  		while sendspec.retry > 0:
  			if sendspec.escape:
  				escaped_str = "eval $'"
  				_count = 7
  				for char in sendspec.send:
  					if char in string.ascii_letters:
  						escaped_str += char
  						_count += 1
  					else:
  						escaped_str += shutit_util.get_wide_hex(char)
  						_count += 4
  					if _count > shutit_global.shutit_global_object.line_limit:
  						# The newline here is deliberate!
  						escaped_str += r"""'\
  $'"""
  						_count = 0
  				escaped_str += "'"
  				if sendspec.secret:
  					shutit.log('The string was sent safely.', level=logging.DEBUG)
  				else:
  					shutit.log('This string was sent safely: ' + sendspec.send, level=logging.DEBUG)
  				string_to_send = escaped_str
  			else:
  				string_to_send = sendspec.send
  			if string_to_send is not None:
  				if len(string_to_send) > shutit_global.shutit_global_object.line_limit:
  					fname = self._create_command_file(sendspec.expect,string_to_send)
  					res = self.send(ShutItSendSpec(self,
  					                               send=' command source ' + fname,
  					                               expect=sendspec.expect,
  					                               timeout=sendspec.timeout,
  					                               check_exit=sendspec.check_exit,
  					                               fail_on_empty_before=False,
  					                               record_command=False,
  					                               exit_values=sendspec.exit_values,
  					                               echo=False,
  					                               escape=False,
  					                               retry=sendspec.retry,
  					                               loglevel=sendspec.loglevel,
  					                               follow_on_commands=sendspec.follow_on_commands,
  					                               delaybeforesend=sendspec.delaybeforesend,
  			                                       nonewline=sendspec.nonewline,
  			                                       run_in_background=sendspec.run_in_background,
  					                               ignore_background=True,
  			                                       block_other_commands=sendspec.block_other_commands))
  					if not self.sendline(ShutItSendSpec(self,
  					                                    send=' rm -f ' + fname,
  					                                    nonewline=sendspec.nonewline,
  			                                            run_in_background=sendspec.run_in_background,
  					                                    echo=False,
  					                                    ignore_background=True)):
  						self.expect(sendspec.expect,
  						            searchwindowsize=sendspec.searchwindowsize,
  						            maxread=sendspec.maxread)
  						# Before returning, determine whether we are now in a shell by comparing the expect we have with the originally-created 'shell_expect'.
  						self.in_shell = sendspec.expect == self.shell_expect
  					return res
  				else:
  					if sendspec.echo:
  						shutit.divert_output(sys.stdout)
  					if not self.sendline(sendspec):
  						expect_res = shutit.expect_allow_interrupt(self.pexpect_child, sendspec.expect, sendspec.timeout)
  					else:
  						expect_res = -1
  					if sendspec.echo:
  						shutit.divert_output(None)
  			else:
  				expect_res = shutit.expect_allow_interrupt(self.pexpect_child, sendspec.expect, sendspec.timeout)
  			if isinstance(self.pexpect_child.after, type) or isinstance(self.pexpect_child.before, type):
  				shutit.log('End of pexpect session detected, bailing.', level=logging.CRITICAL)
  				shutit_global.shutit_global_object.handle_exit(exit_code=1)
  			# Massage the output for summary sending.
  			logged_output = ''.join((self.pexpect_child.before + str(self.pexpect_child.after)).split('\n')).replace(sendspec.send,'',1).replace('\r','')[:160] + ' [...]'
  			if not sendspec.secret:
  				if not sendspec.echo:
  					shutit.log('Output (squashed): ' + logged_output, level=logging.DEBUG)
  				if shutit_global.shutit_global_object.ispy3:
  					shutit.log('pexpect: buffer: ' + str(base64.b64encode(bytes(self.pexpect_child.buffer,shutit_global.shutit_global_object.default_encoding))) + ' before: ' + str(base64.b64encode(bytes(self.pexpect_child.before,shutit_global.shutit_global_object.default_encoding))) + ' after: ' + str(base64.b64encode(bytes(self.pexpect_child.after,shutit_global.shutit_global_object.default_encoding))), level=logging.DEBUG)
  				else:
  					shutit.log('pexpect: buffer: ' + base64.b64encode(self.pexpect_child.buffer) + ' before: ' + base64.b64encode(self.pexpect_child.before) + ' after: '  + base64.b64encode(self.pexpect_child.after), level=logging.DEBUG)
  			else:
  				shutit.log('[Send was marked secret; getting output debug will require code change]', level=logging.DEBUG)
  			if sendspec.fail_on_empty_before:
  				if self.pexpect_child.before.strip() == '':
  					shutit.fail('before empty after sending: ' + str(sendspec.send) + '\n\nThis is expected after some commands that take a password.\nIf so, add fail_on_empty_before=False to the send call.\n\nIf that is not the problem, did you send an empty string to a prompt by mistake?', shutit_pexpect_child=self.pexpect_child) # pragma: no cover
  			else:
  				# Don't check exit if fail_on_empty_before is False
  				sendspec.check_exit = False
  				for prompt in shutit.expect_prompts:
  					if prompt == sendspec.expect:
  						# Reset prompt
  						self.setup_prompt('reset_tmp_prompt')
  						self.revert_prompt('reset_tmp_prompt', sendspec.expect)
  						break
  			# Last output - remove the first line, as it is the previous command.
  			# Get this before we check exit.
  			last_output = '\n'.join(self.pexpect_child.before.split('\n')[1:])
  			if sendspec.check_exit:
  				# store the output
  				if not self.check_last_exit_values(sendspec.send,
  				                                   check_exit=sendspec.check_exit,
  				                                   expect=sendspec.expect,
  				                                   exit_values=sendspec.exit_values,
  				                                   retry=sendspec.retry):
  					if not sendspec.secret:
  						shutit.log('Sending: ' + sendspec.send + ' : failed, retrying', level=logging.DEBUG)
  					else:
  						shutit.log('Send failed, retrying', level=logging.DEBUG)
  					sendspec.retry -= 1
  					assert sendspec.retry > 0, shutit_util.print_debug()
  					continue
  			break
  		# check self.pexpect_child.before for matches for follow-on commands
  		if sendspec.follow_on_commands is not None:
  			for match in sendspec.follow_on_commands:
  				sendspec.send = sendspec.follow_on_commands[match]
  				if shutit.match_string(last_output, match):
  					# send (with no follow-on commands)
  					self.send(ShutItSendSpec(self,
  					                         send=sendspec.send,
  					                         expect=sendspec.expect,
  					                         timeout=sendspec.timeout,
  					                         check_exit=sendspec.check_exit,
  					                         fail_on_empty_before=False,
  					                         record_command=sendspec.record_command,
  					                         exit_values=sendspec.exit_values,
  					                         echo=sendspec.echo,
  					                         escape=sendspec.escape,
  					                         retry=sendspec.retry,
  					                         loglevel=sendspec.loglevel,
  					                         delaybeforesend=sendspec.delaybeforesend,
  			                                 run_in_background=False,
  					                         ignore_background=True,
  			                                 block_other_commands=sendspec.block_other_commands))
  		if shutit.build['step_through']:
  			self.pause_point('pause point: stepping through')
  		if shutit.build['ctrlc_stop']:
  			shutit.build['ctrlc_stop'] = False
  			self.pause_point('pause point: interrupted by CTRL-c')
  		shutit.handle_note_after(note=sendspec.note, training_input=str(sendspec.send))
  		# Before returning, determine whether we are now in a shell by comparing the expect we have with the originally-created 'shell_expect'.
  		self.in_shell = sendspec.expect == self.shell_expect
  		return expect_res