Sample code for 30+ languages & platforms
PureBasic

SSH Remote Shell Multiple Commands

See more SSH Examples

Demonstrates how to start a shell on a remote SSH server, run a command, and retrieve the output, then run the next command, retrieve the output, etc.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkSsh.pb"

Procedure ChilkatExample()

    success.i = 0

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

    ssh.i = CkSsh::ckCreate()
    If ssh.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; This is the prompt we'll be expecting to find in
    ; the output of the remote shell.
    myPrompt.s
    myPrompt = "chilkat@ubuntu:~/workspace$"

    cmdOutput.s

    ; Connect to an SSH server:
    hostname.s
    port.i

    ; Hostname may be an IP address or hostname:
    hostname = "www.some-ssh-server.com"
    port = 22

    success = CkSsh::ckConnect(ssh,hostname,port)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Wait a max of 10 seconds when reading responses..
    CkSsh::setCkIdleTimeoutMs(ssh, 10000)

    ; Authenticate using login/password:
    success = CkSsh::ckAuthenticatePw(ssh,"myLogin","myPassword")
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Open a session channel.  (It is possible to have multiple
    ; session channels open simultaneously.)
    channelNum.i
    channelNum = CkSsh::ckOpenSessionChannel(ssh)
    If channelNum < 0
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    termType.s = "dumb"
    widthInChars.i = 120
    heightInChars.i = 40
    ; Use 0 for pixWidth and pixHeight when the dimensions
    ; are set in number-of-chars.
    pixWidth.i = 0
    pixHeight.i = 0
    success = CkSsh::ckSendReqPty(ssh,channelNum,termType,widthInChars,heightInChars,pixWidth,pixHeight)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Start a shell on the channel:
    success = CkSsh::ckSendReqShell(ssh,channelNum)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ;  Run the 1st command in the remote shell, which will be to
    ;  "cd" to a subdirectory.
    success = CkSsh::ckChannelSendString(ssh,channelNum,"cd workspace" + Chr(13) + Chr(10),"ansi")
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Retrieve the output.
    success = CkSsh::ckChannelReceiveUntilMatch(ssh,channelNum,myPrompt,"ansi",1)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ;  Display what we've received so far.  This clears
    ;  the internal receive buffer, which is important.
    ;  After we send the command, we'll be reading until
    ;  the next command prompt.  If the command prompt
    ;  is already in the internal receive buffer, it'll think it's
    ;  already finished...
    cmdOutput = CkSsh::ckGetReceivedText(ssh,channelNum,"ansi")
    If CkSsh::ckLastMethodSuccess(ssh) <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    Debug cmdOutput

    ;  Run the 2nd command in the remote shell, which will be
    ;  to "ls" the directory.
    success = CkSsh::ckChannelSendString(ssh,channelNum,"ls" + Chr(13) + Chr(10),"ansi")
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Retrieve and display the output.
    success = CkSsh::ckChannelReceiveUntilMatch(ssh,channelNum,myPrompt,"ansi",1)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    cmdOutput = CkSsh::ckGetReceivedText(ssh,channelNum,"ansi")
    If CkSsh::ckLastMethodSuccess(ssh) <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    Debug cmdOutput

    ;  Start the final command in the remote shell.  This example
    ;  will send a "ls -l" command to retrieve the long format directory listing.
    success = CkSsh::ckChannelSendString(ssh,channelNum,"ls -l" + Chr(13) + Chr(10),"ansi")
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Send an EOF.  This tells the server that no more data will 
    ; be sent on this channel.  The channel remains open, and
    ; the SSH client may still receive output on this channel.
    success = CkSsh::ckChannelSendEof(ssh,channelNum)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Read whatever output may already be available on the
    ; SSH connection.  ChannelReadAndPoll returns the number of bytes
    ; that are available in the channel's internal buffer that
    ; are ready to be "picked up" by calling GetReceivedText
    ; or GetReceivedData.
    ; A return value of -1 indicates failure.
    ; A return value of -2 indicates a failure via timeout.

    ; The ChannelReadAndPoll method waits
    ; for data to arrive on the connection usingi the IdleTimeoutMs
    ; property setting.  Once the first data arrives, it continues
    ; reading but instead uses the pollTimeoutMs passed in the 2nd argument:
    ; A return value of -2 indicates a timeout where no data is received.
    n.i
    pollTimeoutMs.i = 2000
    n = CkSsh::ckChannelReadAndPoll(ssh,channelNum,pollTimeoutMs)
    If n < 0
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Close the channel:
    success = CkSsh::ckChannelSendClose(ssh,channelNum)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    ; Perhaps we did not receive all of the commands output.
    ; To make sure,  call ChannelReceiveToClose to accumulate any remaining
    ; output until the server's corresponding "channel close" is received.
    success = CkSsh::ckChannelReceiveToClose(ssh,channelNum)
    If success <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    cmdOutput = CkSsh::ckGetReceivedText(ssh,channelNum,"ansi")
    If CkSsh::ckLastMethodSuccess(ssh) <> 1
        Debug CkSsh::ckLastErrorText(ssh)
        CkSsh::ckDispose(ssh)
        ProcedureReturn
    EndIf

    Debug cmdOutput

    ; Disconnect
    CkSsh::ckDisconnect(ssh)


    CkSsh::ckDispose(ssh)


    ProcedureReturn
EndProcedure