code: func runScripts(
  	ctx context.Context,
  	o terraform.UIOutput,
  	comm communicator.Communicator,
  	scripts []io.ReadCloser) error {
  
  	retryCtx, cancel := context.WithTimeout(ctx, comm.Timeout())
  	defer cancel()
  
  	// Wait and retry until we establish the connection
  	err := communicator.Retry(retryCtx, func() error {
  		return comm.Connect(o)
  	})
  	if err != nil {
  		return err
  	}
  
  	// Wait for the context to end and then disconnect
  	go func() {
  		<-ctx.Done()
  		comm.Disconnect()
  	}()
  
  	for _, script := range scripts {
  		var cmd *remote.Cmd
  
  		outR, outW := io.Pipe()
  		errR, errW := io.Pipe()
  		defer outW.Close()
  		defer errW.Close()
  
  		go copyOutput(o, outR)
  		go copyOutput(o, errR)
  
  		remotePath := comm.ScriptPath()
  
  		if err := comm.UploadScript(remotePath, script); err != nil {
  			return fmt.Errorf("Failed to upload script: %v", err)
  		}
  
  		cmd = &remote.Cmd{
  			Command: remotePath,
  			Stdout:  outW,
  			Stderr:  errW,
  		}
  		if err := comm.Start(cmd); err != nil {
  			return fmt.Errorf("Error starting script: %v", err)
  		}
  
  		if err := cmd.Wait(); err != nil {
  			return err
  		}
  
  		// Upload a blank follow up file in the same path to prevent residual
  		// script contents from remaining on remote machine
  		empty := bytes.NewReader([]byte(""))
  		if err := comm.Upload(remotePath, empty); err != nil {
  			// This feature is best-effort.
  			log.Printf("[WARN] Failed to upload empty follow up script: %v", err)
  		}
  	}
  
  	return nil
  }
docs: // runScripts is used to copy and execute a set of scripts