SSH Kit Gem Part 2

We will explore more examples on SSHKit usage. Finally we will apply our new skills to keep the secrets.yml file synchronized between the local and server.

Example 1


In this example, you will learn how to run commands on a remote server. Create remote-hello.rake in the lib/tasks folder.

require 'sshkit/dsl'

SSHKit::Backend::Netssh.configure do |ssh|
  ssh.ssh_options = {
      user: 'rails',
      auth_methods: ['publickey']
  }
end

desc 'Who am I on the server'
task :who do

  on 'www.rubyplus.com' do
    as :root do
      execute 'whoami'
    end
  end

end

I have copied my public key to my server so that I can securely connect to it without having to enter my password. You can see that I have specified auth_methods: ['publickey'] in the setup. The on() method takes the server name to run the command. The as() method takes the user as the argument. So the execute command will run the whoami as root. This is a trivial example, but it shows how to remotely execute commands on a given server.

$rake who
DEBUG[853f1298] Finished in 1.634 seconds with exit status 0 (successful).
INFO[a7d95d3d] Running /usr/bin/env whoami on www.rubyplus.com
DEBUG[a7d95d3d] Command: sudo -u root -- sh -c '/usr/bin/env whoami'
DEBUG[a7d95d3d]     root
INFO[a7d95d3d] Finished in 0.155 seconds with exit status 0 (successful).

The output shows that I am 'root' as the result of running the whoami command. You can accomplish the same thing by using capture command instead of execute command:

task :whoami do
  on 'www.rubyplus.com' do 
    as 'root' do
      puts capture(:whoami)
    end
  end
end
$rake whoami
DEBUG[ef246db2] Finished in 1.427 seconds with exit status 0 (successful).
DEBUG[46f56882] Running /usr/bin/env whoami on www.rubyplus.com
DEBUG[46f56882] Command: sudo -u root -- sh -c '/usr/bin/env whoami'
DEBUG[46f56882]     root
DEBUG[46f56882] Finished in 0.156 seconds with exit status 0 (successful).
root

Example 2


Add the following task:

task :check_env do
  on 'www.rubyplus.com' do 
    puts capture(:env)
  end  
end

This prints the env variables set on the server.

Example 3


Here is a task to check the log file:

task :check_log do
  on 'www.rubyplus.com' do
    within '/var/www/blog/shared/log' do
      puts capture(:head, '-n5', 'sucker_punch.log')
    end
  end
end
$rake check_log
DEBUG[a97e36b2] Running /usr/bin/env if test ! -d /var/www/blog/shared/log; then echo "Directory does not exist '/var/www/blog/shared/log'" 1>&2; false; fi on www.rubyplus.com
DEBUG[a97e36b2] Command: if test ! -d /var/www/blog/shared/log; then echo "Directory does not exist '/var/www/blog/shared/log'" 1>&2; false; fi
DEBUG[a97e36b2] Finished in 1.397 seconds with exit status 0 (successful).
DEBUG[6ef963e1] Running /usr/bin/env head -n5 sucker_punch.log on www.rubyplus.com
DEBUG[6ef963e1] Command: cd /var/www/blog/shared/log && /usr/bin/env head -n5 sucker_punch.log
DEBUG[6ef963e1]     # Logfile created on 2014-08-16 20:28:41 +0000 by logger.rb/44203
DEBUG[6ef963e1] Finished in 0.147 seconds with exit status 0 (successful).
# Logfile created on 2014-08-16 20:28:41 +0000 by logger.rb/44203

Example 4


To check how long the server has been up.

task :check_uptime do
  on 'rubyplus.com' do
    execute :uptime
  end
end
$rake check_uptime
INFO[799d57f4] Running /usr/bin/env uptime on rubyplus.com
DEBUG[799d57f4] Command: /usr/bin/env uptime
DEBUG[799d57f4]      10:32:43 up 38 days,  9:45,  0 users,  load average: 0.00, 0.01, 0.05
INFO[799d57f4] Finished in 1.560 seconds with exit status 0 (successful).

Example 5


Here is a task to print the working directory.

task :pwd do
  on 'rubyplus.com' do
    execute :pwd
  end  
end
$rake pwd
INFO[a870efb4] Running /usr/bin/env pwd on rubyplus.com
DEBUG[a870efb4] Command: /usr/bin/env pwd
DEBUG[a870efb4]     /home/rails
INFO[a870efb4] Finished in 1.609 seconds with exit status 0 (successful).

Example 6


Here is an example on how to execute command with flags.

task :unameit do
  on 'rubyplus.com' do
    execute('uname -a')
  end
end
$rake unameit
INFO[def8cdee] Running /usr/bin/env uname -a on rubyplus.com
DEBUG[def8cdee] Command: uname -a
DEBUG[def8cdee]     Linux li552-13 3.15.4-x86_64-linode45 #1 SMP Mon Jul 7 08:42:36 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux
INFO[def8cdee] Finished in 1.506 seconds with exit status 0 (successful).

You can accomplish the same thing using capture command. Let's run the 'uname -a' command on the remote server using capture.

on 'rubyplus.com' do
  capture(:uname, '-a')
end
$ruby lib/tasks/apache.rb

DEBUG[d116fd09] Running /usr/bin/env uname -a on rubyplus.com
DEBUG[d116fd09] Command: /usr/bin/env uname -a
DEBUG[d116fd09]     Linux li552-13 3.15.4-x86_64-linode45 #1 SMP Mon Jul 7 08:42:36 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux
DEBUG[d116fd09] Finished in 1.592 seconds with exit status 0 (successful).

Example 7


Here is an example for using a flag and an argument in the execute() method.

require 'sshkit'
require 'sshkit/dsl'

SSHKit::Backend::Netssh.configure do |ssh|
  ssh.ssh_options = {
      user: 'rails',
      auth_methods: ['publickey']
  }
end

SSHKit.config.output_verbosity = :debug

on 'rubyplus.com' do
  execute :ls, '-l', '/home/rails'
end  
$ruby lib/tasks/apache.rb

INFO[c43630e8] Running /usr/bin/env ls -l /home/rails on rubyplus.com
DEBUG[c43630e8] Command: /usr/bin/env ls -l /home/rails

DEBUG[c43630e8]     total 4
DEBUG[c43630e8]     -rw-r--r-- 1 rails rails 401 Jul  9 05:02 my_key.pub
INFO[c43630e8] Finished in 2.367 seconds with exit status 0 (successful).

This is not a rake task, this is just a ruby script.

Example 8


Let's run echo command on the remote server.

on 'rubyplus.com' do
  capture(:echo, 'hello sshkit')
end
ruby lib/tasks/apache.rb
DEBUG[b1e5c25d] Running /usr/bin/env echo hello sshkit on rubyplus.com
DEBUG[b1e5c25d] Command: /usr/bin/env echo hello sshkit
DEBUG[b1e5c25d]     hello sshkit
DEBUG[b1e5c25d] Finished in 1.538 seconds with exit status 0 (successful).

Example 9


Here is an useful check to see if all the gem dependencies are satisfied on the remote server.

on 'rubyplus.com' do
  within('/var/www/blog/current') do
    capture(:bundle, 'check')
  end
end
$ruby lib/tasks/apache.rb

DEBUG[e126b7e1] Running /usr/bin/env if test ! -d /var/www/blog/current; then echo "Directory does not exist '/var/www/blog/current'" 1>&2; false; fi on rubyplus.com
DEBUG[e126b7e1] Command: if test ! -d /var/www/blog/current; then echo "Directory does not exist '/var/www/blog/current'" 1>&2; false; fi

DEBUG[e126b7e1] Finished in 1.506 seconds with exit status 0 (successful).
DEBUG[bb8eb516] Running /usr/bin/env bundle check on rubyplus.com
DEBUG[bb8eb516] Command: cd /var/www/blog/current && /usr/bin/env bundle check
DEBUG[bb8eb516]     The Gemfile's dependencies are satisfied
DEBUG[bb8eb516] Finished in 0.537 seconds with exit status 0 (successful).

Keeping Files in Synch


Let's now see how to keep the secrets.yml in Synch. Add show_secrets rake task to your .rake file.

SSHKit.config.output_verbosity = :debug

task :show_secrets  do  
  run_locally do
    execute "cat ~/projects/blog/config/secrets.yml"
  end
end

This will show the contents of Rails blog project's secrets.yml file on your local machine.

task :remote_secrets do
  on 'rubyplus.com' do
    within('/var/www/blog/shared') do
      capture(:cat, 'config/secrets.yml')
    end
  end
end

This will display the contents of the secrets.yml file on the server. You can run rake :show_secrets and rake :remote_secrets from your local machine rails root directory. Let's keep the secrets.yml synchronized between the local and the server.

If it is not the same, then upload the local secrets to the remote /shared/config/secrets.yml by running rake upload_secrets.

task :upload_secrets do
  on 'www.rubyplus.com' do |host|
    file = File.open("#{Rails.root}/config/secrets.yml")
    upload! file, '/var/www/blog/shared/secrets.yml'
  end
end


Related Articles


Create your own user feedback survey