Sample code for 30+ languages & platforms
Lua

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 Lua Downloads

Lua
local chilkat = require("chilkat")

-- 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.

local ssh1 = chilkat.Ssh.new()
local ssh2 = chilkat.Ssh.new()
local ssh3 = chilkat.Ssh.new()

local port = 22

-- 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.
local password = "mySshPassword"

local success = ssh1:connect("ssh-server1.example.com", port)
if not success then
    print(ssh1.last_error_text)
    return
end

success = ssh1:authenticate_pw("mySshLogin", password)
if not success then
    print(ssh1.last_error_text)
    return
end

success = ssh2:connect("ssh-server2.example.com", port)
if not success then
    print(ssh2.last_error_text)
    return
end

success = ssh2:authenticate_pw("mySshLogin", password)
if not success then
    print(ssh2.last_error_text)
    return
end

success = ssh3:connect("ssh-server3.example.com", port)
if not success then
    print(ssh3.last_error_text)
    return
end

success = ssh3:authenticate_pw("mySshLogin", password)
if not success then
    print(ssh3.last_error_text)
    return
end

-- This command sleeps for 5 seconds and then prints the system date/time, making the parallel
-- execution easy to observe.
local cmd = "sleep 5; date"

-- Start the command on each server.  QuickCmdSend returns immediately.
local channel1 = ssh1:quick_cmd_send(cmd)
if channel1 < 0 then
    print(ssh1.last_error_text)
    return
end

local channel2 = ssh2:quick_cmd_send(cmd)
if channel2 < 0 then
    print(ssh2.last_error_text)
    return
end

local channel3 = ssh3:quick_cmd_send(cmd)
if channel3 < 0 then
    print(ssh3.last_error_text)
    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.)
local pollTimeoutMs = 50
local numFinished = 0
local finished1 = false
local finished2 = false
local finished3 = false

while numFinished < 3 do
    if not finished1 then
        local ch1 = ssh1:quick_cmd_check(pollTimeoutMs)
        if ch1 == (-2) then
            print(ssh1.last_error_text)
            return
        end

        if ch1 >= 0 then
            print("---- ssh1 channel " .. ch1 .. " finished ----")
            local out1 = ssh1:get_received_text(ch1, "utf-8")
            if not ssh1.last_method_success then
                print(ssh1.last_error_text)
                return
            end

            print(out1)
            finished1 = true
            numFinished = numFinished + 1
        end
    end

    if not finished2 then
        local ch2 = ssh2:quick_cmd_check(pollTimeoutMs)
        if ch2 == (-2) then
            print(ssh2.last_error_text)
            return
        end

        if ch2 >= 0 then
            print("---- ssh2 channel " .. ch2 .. " finished ----")
            local out2 = ssh2:get_received_text(ch2, "utf-8")
            if not ssh2.last_method_success then
                print(ssh2.last_error_text)
                return
            end

            print(out2)
            finished2 = true
            numFinished = numFinished + 1
        end
    end

    if not finished3 then
        local ch3 = ssh3:quick_cmd_check(pollTimeoutMs)
        if ch3 == (-2) then
            print(ssh3.last_error_text)
            return
        end

        if ch3 >= 0 then
            print("---- ssh3 channel " .. ch3 .. " finished ----")
            local out3 = ssh3:get_received_text(ch3, "utf-8")
            if not ssh3.last_method_success then
                print(ssh3.last_error_text)
                return
            end

            print(out3)
            finished3 = true
            numFinished = numFinished + 1
        end
    end
end

ssh1:disconnect()
ssh2:disconnect()
ssh3:disconnect()