code: @WorkerThread
    public static CommandResult run(@NonNull String shell, @NonNull String... commands) {
      return run(shell, commands, null);
    }
docs: <p>Runs commands using the supplied shell, and returns the result.</p>
  
  <p>When in debug mode, the code will also excessively log the commands passed to and the output returned from
  the shell.</p>
  
  <p>Though this function uses background threads to gobble stdout and stderr so a deadlock does not occur if the
  shell produces massive output, the output is still stored in a List&lt;String&gt;, and as such doing something
  like <em>'ls -lR /'</em> will probably have you run out of memory.</p>
  
  @param shell
  The shell to use for executing the commands
  @param commands
  The commands to execute
  @return Output of the commands, or null in case of an error