You want to securely send data or commands back and forth between your computer, and another computer on which you have a shell account.
Use the Net::SSH module, which implements the SSH2 protocol. Its found in the net-ssh gem, although some operating systems package it themselves.[2] It lets you implement Ruby applications that work like the familiar ssh and scp.
[2] For instance, its available on Debian GNU/Linux as the package libnet-ssh-ruby1.8.
You can start an SSH session by passing a hostname to Net::SSH::start, along with your shell username and password on that host. If you have an SSH public/private key pair set up between your computer and the remote host, you can omit the username and password:
require ubygems require et/ssh Net::SSH.start(example.com, :username=>leonardr, :password=>mypass) do |session| # Manipulate your Net::SSH::Session object here… end
Net::SSH::start takes a code block, to which it passes a Net::SSH::Session object. You use the session object to send encrypted data between the machines, or to spawn processes on the remote machine. When the code block ends, the SSH session is automatically terminated.
It seems strange now, but until the late 1990s, people routinely used unsecured protocols like telnet to get shell access to remote machines. Remote access was so useful that we were willing to jeopardize our electronic safety by sending our shell passwords (not to mention all the data we looked at) unencrypted across the network. Fortunately, we don have to make that trade-off anymore. The SSH protocol makes it easy to send encrypted traffic between machines, and the client tools ssh and scp have almost completely replaced tools like RSH and nonanonymous FTP.
The Net::SSH library provides a low-level interface to the SSH2 protocol, but most of the time you won need it. Instead, youll use one of the abstractions that make it easy to spawn and control processes on a remote machine. The simplest abstraction is the popen3 method, which works like the local popen3 method in Rubys open3 library. Its covered in more detail in Recipe 20.10, but heres a simple example:
Net::SSH.start(example.com, :username=>leonardr, :password=>mypass) do |session| cmd = ls -l /home/leonardr/test_dir session.process.popen3(cmd) do |stdin, stdout, stderr| puts stdout.read end end # -rw-rw-r-- 1 leonardr leonardr 33 Dec 29 20:40 file1 # -rw-rw-r-- 1 leonardr leonardr 102 Dec 29 20:40 file2
You can run a sequence of commands in a single user shell by calling session.shell.sync:
Net::SSH.start(example.com, :username=>leonardr, :password=>mypass) do |session| shell = session.shell.sync puts "Original working directory: #{shell.pwd.stdout}" shell.cd est_dir puts "Working directory now: #{shell.pwd.stdout}" puts Directory contents: puts shell.ls("-l").stdout shell.exit end # Original working directory: /home/leonardr # Working directory now: /home/leonardr/test_dir # Directory contents: # -rw-rw-r--1 leonardr leonardr 33 Dec 29 20:40 file1 # -rw-rw-r--1 leonardr leonardr 102 Dec 29 20:40 file2
The main downside of a synchronized shell is that you usually can pass standard input data into the commands you run. Theres no way to close the standard input stream, so the process will hang forever waiting for more standard input.[3] To pass standard input into a remote process, you should use popen3. With a little trickery, you can control multiple processes simultaneously through your SSH connection; see Recipe 14.11 for details.
[3] The exception is a command like bc, which terminates itself if it sees the line "quit " in its standard input. Commands like cat always look for more standard input.
If your public/private key pair for a host is protected by a passphrase, you will be prompted for the passphrase Net::SSH tries to make a connection to that host. This makes your key more secure, but it will foil your plans to use Net::SSH in an automated script.
You can also use Net::SSH to do TCP/IP port forwarding. As of this writing, you can use it to do X11 forwarding.
Strings
Numbers
Date and Time
Arrays
Hashes
Files and Directories
Code Blocks and Iteration
Objects and Classes8
Modules and Namespaces
Reflection and Metaprogramming
XML and HTML
Graphics and Other File Formats
Databases and Persistence
Internet Services
Web Development Ruby on Rails
Web Services and Distributed Programming
Testing, Debugging, Optimizing, and Documenting
Packaging and Distributing Software
Automating Tasks with Rake
Multitasking and Multithreading
User Interface
Extending Ruby with Other Languages
System Administration