execList method

void execList({
  1. required String host,
  2. required List<String?> commands,
  3. bool agent = true,
  4. bool sudo = false,
  5. String? password,
  6. Progress? progress,
})

execList runs multiple commands in a single request to the host.

The commands are chained into a single command line with the bash command delimiter ';' betwen each command.

If you set sudo to true then each command is run under sudo. If you set password then the password is passed to the sudo command.

  Remote.exec(
    host: fqdn,
    command: ['mkdir -p /tmp/dir/fred', 'cp /home/bsutton/*.dart /tmp/dir/fred', 'ls /tmp/dir/fred/*.dart'],
    sudo: true,
    password: password,
    progress: Progress.print());

Implementation

void execList({
  required String host,
  required List<String?> commands,
  bool agent = true,
  bool sudo = false,
  String? password,
  Progress? progress,
}) {
  final cmdArgs = <String>[];

  // enable agent forwarding only
  // if the user doesn't pass a password.
  if (agent && password == null) {
    cmdArgs.add('-A');
  }
  // disable psuedo terminal
  cmdArgs
    ..add('-T')
    ..add(host);

  final cmdLine = StringBuffer();
  for (var command in commands) {
    if (sudo) {
      // -S accept echoed password{
      // -k clear the sudo cached password so it expects a password

      // We quote the [command] to stop glob expansion on the local system.
      if (password != null) {
        command = "echo $password | sudo -Skp '' $command";
      } else {
        command = 'sudo $command';
      }
    }
    if (cmdLine.isNotEmpty) {
      // bash command delimiter.
      cmdLine.write(';');
    }
    cmdLine.write(command);
  }

  cmdArgs.add('"$cmdLine"');

  progress ??= Progress.devNull();

  try {
    startFromArgs('ssh', cmdArgs, progress: progress);
  } on RunException catch (e) {
    final error = _sshErrors[e.exitCode!];
    throw RunException(
      e.cmdLine,
      e.exitCode,
      red('ssh exit code: ${e.exitCode} - $error'),
      stackTrace: e.stackTrace,
    );
  }
}