Open4ssh is a small convenience wrapper for net-ssh. Its intended and primary purpose is to provide pragmatic execution of shell commands on a remote host via SSH.
It is mainly inspired by Open3 standard library which provides access to exit codes, standard output and standard error messages of executed commands on local host. Open4ssh does the same but in a SSH remote context. Astonishingly, there seems no pragmatic way to figure out exit codes or standard error messages of executed commands with the net-ssh library. Additionally, Open4ssh is able to execute a sequence of commands and returns their exit codes, standard out and standard error messages in a command related list.
Open4ssh is most useful in remote automation scenarios which are triggered from Ruby environments.
- RubyGems
- Master:
- Develop:
Add this line to your application's Gemfile:
gem 'open4ssh'
And then execute:
$ bundle
Or install it yourself as:
$ gem install open4ssh
All parameters of the capture()
command are explained here.
However, the following snippets explain how to use Open4ssh. To execute simply one single command on a remote host, we can do the following:
require 'open4ssh'
stdout = Open4ssh.capture(
host: 'remote.host.io',
user: 'nane',
pwd: 'secret',
cmd: 'ls -la'
)
puts stdout
This will execute the bash command 'ls -la' on host remote.host.io as user nane.
For a lot of cloud scenarios it is more appropriate to support a keybased login. This can be done like that (simply use the key parameter instead of the pwd parameter):
require 'open4ssh'
stdout = Open4ssh.capture(
host: 'remote.host.io',
user: 'nane',
key: '/path/to/your/sshkey.pem',
cmd: 'ls -la'
)
puts stdout
All parameters of the capture4()
function are explained here.
The following snippets will explain how to use Open4ssh to execute a (sequence) of commands.
This snippet here will execute five shell commands sequentially
require 'open4ssh'
require 'pp'
returns = Open4ssh.capture4(
host: 'remote.host.io',
user: 'nane',
key: '/path/to/your/sshkey.pem',
cmd: [
"touch helloworld.txt",
"cat helloworld.txt",
"echo 'Hello World' >> helloworld.txt",
"cat helloworld.txt",
"rm helloworld.txt"
]
)
pp(returns)
and will generate this output.
[[0, "", "", "touch helloworld.txt"],
[0, "", "", "cat helloworld.txt"],
[0, "", "", "echo 'Hello World' >> helloworld.txt"],
[0, "Hello World\n", "", "cat helloworld.txt"],
[0, "", "", "rm helloworld.txt"]]
So, for each command a list of return values is returned.
- exit code of the executed command
- standard out message (might be empty)
- standard error message (might be empty)
- executed command (as passed by the cmd parameter)
However, if we launch a sequence of commands exiting with exit codes not equal 0, this sequence is only executed as long as each command could be successfully processed (exit code 0). So this snippet here
require 'open4ssh'
require 'pp'
returns = Open4ssh.capture4(
host: 'remote.host.io',
user: 'nane',
key: '/path/to/your/sshkey.pem',
cmd: [
"touch helloworld.txt",
"cat helloworld.txt",
"this will not work",
"cat helloworld.txt",
"rm helloworld.txt"
]
)
pp(returns)
would produce the following output
[[0, "", "", "touch helloworld.txt"],
[0, "", "", "cat helloworld.txt"],
[127, "", "bash: this: command not found\n", "this will not work"]]
and the last two commands would not been executed on the remote host, because the third command failed.
Because Open4ssh only executes commands as long as they are returning a exit code of 0, we can check pragmatically whether all commands of a sequence have been executed successfully:
returns = Open4ssh.capture4(
host: 'remote.host.io',
user: 'nane',
key: '/path/to/your/sshkey.pem',
cmd: [
"touch helloworld.txt",
"cat helloworld.txt",
"echo 'Hello World' >> helloworld.txt",
"cat helloworld.txt",
"rm helloworld.txt"
]
)
if Open4ssh.success(returns)
puts "Everything worked fine"
end
If you want to know what is happening there you can turn on the verbose mode (mostly useful for debugging).
returns = Open4ssh.capture4(
host: 'remote.host.io',
user: 'nane',
key: '/path/to/your/sshkey.pem',
cmd: [
"curl -fsSL https://test.docker.com/ | sh",
"sudo docker swarm init"
],
verbose: true
)
if Open4ssh.success(returns)
puts "You started successfully a new Docker Swarm cluster."
end
This will perform the same install like above but will print all messages of the Docker install script on your console.
It is possible to print all standard output and error messages of
sequentially executed commands by calling stdout()
, stderr()
or console()
with the return of a capture4()
call.
# This will print all standard output messages of all executed commands.
puts Open4ssh.stdout(returns)
# This will print all standard error messages of all executed commands.
puts Open4ssh.stderr(returns)
# This will print all console output messages of all executed commands
# (which includes standard out and standard err messages).
puts Open4ssh.console(returns)
Just a small example. Assuming your remote host is a Ubuntu 14.04 system we could do something like that:
returns = Open4ssh.capture4(
host: 'remote.host.io',
user: 'nane',
key: '/path/to/your/sshkey.pem',
cmd: [
"curl -fsSL https://test.docker.com/ | sh",
"sudo docker swarm init"
]
)
if Open4ssh.success(returns)
puts "You started successfully a new Docker Swarm cluster."
end
This would fire up an initial master for a Docker Swarm cluster in a few lines of Ruby code. Be patient. This can take several minutes. Of course, you can do any other tasks as well. This was only one example ;-)
To install this gem onto your local machine, run bundle exec rake install
.
To release a new version, update the version number in version.rb
,
and then run bundle exec rake release
,
which will create a git tag for the version,
push git commits and tags, and push the .gem
file to rubygems.org.
All kind of
- bug reports,
- feature requests,
- and pull requests
are welcome on Github at https://github.com/nkratzke/open4ssh.
The gem is available as open source under the terms of the MIT License.