Sample code for 30+ languages & platforms
Pascal (Lazarus/Delphi)

SSH Parallel Remote Commands on Multiple Servers

See more SSH Examples

Shows how to execute a command in parallel on multiple servers.

Chilkat Pascal (Lazarus/Delphi) Downloads

Pascal (Lazarus/Delphi)
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.Ssh;

// ---------------------------------------------------------------------------

procedure RunDemo;
var
  success: Boolean;
  ssh1: TSsh;
  ssh2: TSsh;
  ssh3: TSsh;
  port: Integer;
  cmd: string;
  ssh1Channel: Integer;
  ssh2Channel: Integer;
  ssh3Channel: Integer;
  pollTimeoutMs: Integer;
  numFinished: Integer;
  channel: Integer;
  ssh1Finished: Boolean;
  ssh2Finished: Boolean;
  ssh3Finished: Boolean;

begin
  success := False;

  //  This example requires the Chilkat API to have been previously unlocked.
  //  See Global Unlock Sample for sample code.

  //  Executing a command on multiple servers simultaneously is straightforward.
  //  It's just a matter of using one SSH object per server..
  ssh1 := TSsh.Create;
  ssh2 := TSsh.Create;
  ssh3 := TSsh.Create;

  port := 22;
  success := ssh1.Connect('ssh-server1.com',port);
  if (success <> True) then
    begin
      WriteLn(ssh1.LastErrorText);
      Exit;
    end;

  //  Authenticate using login/password:
  success := ssh1.AuthenticatePw('sshLogin1','sshPassword1');
  if (success <> True) then
    begin
      WriteLn(ssh1.LastErrorText);
      Exit;
    end;

  //  Connect and authenticate with 2 more servers.
  //  For brevity, the success/failure won't be checked...
  success := ssh2.Connect('ssh-server2.com',port);
  success := ssh2.AuthenticatePw('sshLogin2','sshPassword2');
  success := ssh3.Connect('ssh-server3.com',port);
  success := ssh3.AuthenticatePw('sshLogin3','sshPassword3');

  //  Note: If we wanted, we could've used ConnectAsync and AuthenticatePwAsync
  //  to do the connecting and authenticating in parallel...

  //  The command to be run on each SSH server will sleep for 5 seconds,
  //  and then show the current system date/time.
  cmd := 'sleep 5; date';

  //  Start each command
  ssh1Channel := ssh1.QuickCmdSend(cmd);
  if (ssh1Channel < 0) then
    begin
      WriteLn(ssh1.LastErrorText);
      Exit;
    end;
  //  For brevity, we're not checking the return values here:
  ssh2Channel := ssh2.QuickCmdSend(cmd);
  ssh3Channel := ssh3.QuickCmdSend(cmd);

  //  OK, at this point the command is running simultaneously on each server.

  //  Now collect the results of each command.
  pollTimeoutMs := 50;
  numFinished := 0;

  //  Note: You would rewrite this code to use arrays.
  ssh1Finished := False;
  ssh2Finished := False;
  ssh3Finished := False;
  while numFinished < 3 do
    begin
      //  Check to see if anything has finished.
      //  QuickCmdCheck returns -1 if there are no errors and nothing else finished
      //  QuickCmdCheck returns -2 if there was an error (such as a lost connection)
      //  QuickCmdCheck returns a channel number if a channel finished.
      if (ssh1Finished <> True) then
        begin
          channel := ssh1.QuickCmdCheck(pollTimeoutMs);
          if (channel = -2) then
            begin
              WriteLn(ssh1.LastErrorText);
              Exit;
            end;
          if (channel = ssh1Channel) then
            begin
              WriteLn('---- ssh1 channel ' + channel + ' finished ----');
              WriteLn(ssh1.GetReceivedText(channel,'ansi'));
              numFinished := numFinished + 1;
              ssh1Finished := True;
            end;
        end;
      if (ssh2Finished <> True) then
        begin
          channel := ssh2.QuickCmdCheck(pollTimeoutMs);
          if (channel = -2) then
            begin
              WriteLn(ssh2.LastErrorText);
              Exit;
            end;
          if (channel = ssh2Channel) then
            begin
              WriteLn('---- ssh2 channel ' + channel + ' finished ----');
              WriteLn(ssh2.GetReceivedText(channel,'ansi'));
              numFinished := numFinished + 1;
              ssh2Finished := True;
            end;
        end;
      if (ssh3Finished <> True) then
        begin
          channel := ssh3.QuickCmdCheck(pollTimeoutMs);
          if (channel = -2) then
            begin
              WriteLn(ssh3.LastErrorText);
              Exit;
            end;
          if (channel = ssh3Channel) then
            begin
              WriteLn('---- ssh3 channel ' + channel + ' finished ----');
              WriteLn(ssh3.GetReceivedText(channel,'ansi'));
              numFinished := numFinished + 1;
              ssh3Finished := True;
            end;
        end;

    end;

  //  --------------
  //  Sample output:

  //  	---- ssh2 channel 101 finished ----
  //  	Fri Dec 23 00:25:48 UTC 2016
  //  
  //  	---- ssh3 channel 102 finished ----
  //  	Thu Dec 22 18:25:12 CST 2016
  //  
  //  	---- ssh1 channel 100 finished ----
  //  	Thu Dec 22 18:25:48 CST 2016


  ssh1.Free;
  ssh2.Free;
  ssh3.Free;

end;

// ---------------------------------------------------------------------------

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.