Sample code for 30+ languages & platforms
DataFlex

SSH Parallel Remote Commands on Multiple Servers

See more SSH Examples

Demonstrates running the same command on several servers simultaneously. It is simply a matter of using one Ssh object per server, starting the command on each with QuickCmdSend, and then polling each connection with QuickCmdCheck until all have finished.

Background: This is the fan-out pattern behind configuration-management and monitoring tools: query or update a whole fleet in roughly the time the slowest single host takes, rather than the sum of all of them. Each server needs its own object because each has its own connection and authentication state. Note that results come back in whatever order the servers finish, which is why the example tracks completion per connection. Production code would keep the objects in arrays instead of repeating the logic per server.

Chilkat DataFlex Downloads

DataFlex
Use ChilkatAx-win32.pkg

Procedure Test
    Boolean iSuccess
    Handle hoSsh1
    Handle hoSsh2
    Handle hoSsh3
    Integer iPort
    String sPassword
    String sCmd
    Integer iChannel1
    Integer iChannel2
    Integer iChannel3
    Integer iPollTimeoutMs
    Integer iNumFinished
    Boolean iFinished1
    Boolean iFinished2
    Boolean iFinished3
    Integer iCh1
    String sOut1
    Integer iCh2
    String sOut2
    Integer iCh3
    String sOut3
    String sTemp1
    Boolean bTemp1

    Move False To iSuccess

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

    //  Demonstrates running the same command on several servers simultaneously.  It is simply a
    //  matter of using one Ssh object per server.

    Get Create (RefClass(cComChilkatSsh)) To hoSsh1
    If (Not(IsComObjectCreated(hoSsh1))) Begin
        Send CreateComObject of hoSsh1
    End
    Get Create (RefClass(cComChilkatSsh)) To hoSsh2
    If (Not(IsComObjectCreated(hoSsh2))) Begin
        Send CreateComObject of hoSsh2
    End
    Get Create (RefClass(cComChilkatSsh)) To hoSsh3
    If (Not(IsComObjectCreated(hoSsh3))) Begin
        Send CreateComObject of hoSsh3
    End

    Move 22 To iPort

    //  Normally you would not hard-code the password in source.  You should instead obtain it
    //  from an interactive prompt, environment variable, or a secrets vault.
    Move "mySshPassword" To sPassword

    Get ComConnect Of hoSsh1 "ssh-server1.example.com" iPort To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh1 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComAuthenticatePw Of hoSsh1 "mySshLogin" sPassword To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh1 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComConnect Of hoSsh2 "ssh-server2.example.com" iPort To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh2 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComAuthenticatePw Of hoSsh2 "mySshLogin" sPassword To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh2 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComConnect Of hoSsh3 "ssh-server3.example.com" iPort To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh3 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComAuthenticatePw Of hoSsh3 "mySshLogin" sPassword To iSuccess
    If (iSuccess = False) Begin
        Get ComLastErrorText Of hoSsh3 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  This command sleeps for 5 seconds and then prints the system date/time, making the parallel
    //  execution easy to observe.
    Move "sleep 5; date" To sCmd

    //  Start the command on each server.  QuickCmdSend returns immediately.
    Get ComQuickCmdSend Of hoSsh1 sCmd To iChannel1
    If (iChannel1 < 0) Begin
        Get ComLastErrorText Of hoSsh1 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComQuickCmdSend Of hoSsh2 sCmd To iChannel2
    If (iChannel2 < 0) Begin
        Get ComLastErrorText Of hoSsh2 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    Get ComQuickCmdSend Of hoSsh3 sCmd To iChannel3
    If (iChannel3 < 0) Begin
        Get ComLastErrorText Of hoSsh3 To sTemp1
        Showln sTemp1
        Procedure_Return
    End

    //  The command is now running on all three servers at once.  Poll each connection until every
    //  command has finished.  (Production code would keep the objects in arrays rather than
    //  repeating the logic.)
    Move 50 To iPollTimeoutMs
    Move 0 To iNumFinished
    Move False To iFinished1
    Move False To iFinished2
    Move False To iFinished3

    While (iNumFinished < 3)
        If (Not iFinished1) Begin
            Get ComQuickCmdCheck Of hoSsh1 iPollTimeoutMs To iCh1
            If (iCh1 = -2) Begin
                Get ComLastErrorText Of hoSsh1 To sTemp1
                Showln sTemp1
                Procedure_Return
            End

            If (iCh1 >= 0) Begin
                Showln "---- ssh1 channel " iCh1 " finished ----"
                Get ComGetReceivedText Of hoSsh1 iCh1 "utf-8" To sOut1
                Get ComLastMethodSuccess Of hoSsh1 To bTemp1
                If (bTemp1 = False) Begin
                    Get ComLastErrorText Of hoSsh1 To sTemp1
                    Showln sTemp1
                    Procedure_Return
                End

                Showln sOut1
                Move True To iFinished1
                Move (iNumFinished + 1) To iNumFinished
            End

        End

        If (Not iFinished2) Begin
            Get ComQuickCmdCheck Of hoSsh2 iPollTimeoutMs To iCh2
            If (iCh2 = -2) Begin
                Get ComLastErrorText Of hoSsh2 To sTemp1
                Showln sTemp1
                Procedure_Return
            End

            If (iCh2 >= 0) Begin
                Showln "---- ssh2 channel " iCh2 " finished ----"
                Get ComGetReceivedText Of hoSsh2 iCh2 "utf-8" To sOut2
                Get ComLastMethodSuccess Of hoSsh2 To bTemp1
                If (bTemp1 = False) Begin
                    Get ComLastErrorText Of hoSsh2 To sTemp1
                    Showln sTemp1
                    Procedure_Return
                End

                Showln sOut2
                Move True To iFinished2
                Move (iNumFinished + 1) To iNumFinished
            End

        End

        If (Not iFinished3) Begin
            Get ComQuickCmdCheck Of hoSsh3 iPollTimeoutMs To iCh3
            If (iCh3 = -2) Begin
                Get ComLastErrorText Of hoSsh3 To sTemp1
                Showln sTemp1
                Procedure_Return
            End

            If (iCh3 >= 0) Begin
                Showln "---- ssh3 channel " iCh3 " finished ----"
                Get ComGetReceivedText Of hoSsh3 iCh3 "utf-8" To sOut3
                Get ComLastMethodSuccess Of hoSsh3 To bTemp1
                If (bTemp1 = False) Begin
                    Get ComLastErrorText Of hoSsh3 To sTemp1
                    Showln sTemp1
                    Procedure_Return
                End

                Showln sOut3
                Move True To iFinished3
                Move (iNumFinished + 1) To iNumFinished
            End

        End

    Loop

    Send ComDisconnect To hoSsh1
    Send ComDisconnect To hoSsh2
    Send ComDisconnect To hoSsh3


End_Procedure