有没有这样一个需求:
同时向几十上百台Linux服务器上传文件并执行命令,如果一个个来,那你就真是挨踢民工。程序员要发挥自己懒惰的个性,借用Net::SSH和net::SCP用Ruby写个脚本你会发现非常简单。
Net::SSH和Net::SCP是两个Ruby操作SSH的gem包。Net::SSH相当于cmd,专门用于执行命令;Net::SCP专门用于传输文件。它们俩结合,可以做任何SSH client能做的事情。
gem install net-ssh gem install net-scp
以下所有代码都引用这段代码
require 'net/ssh' require 'net/scp' HOST = '192.168.1.1' USER = 'username' PASS = 'password'
Net::SSH.start( HOST, USER, :password => PASS ) do |ssh| result = ssh.exec!('ls') puts result end
Net::SSH.start会与目标主机建立一个连接,并返回一个代表连接的session。如果后面接收一个block,会在block结束时自动关闭连接。否则要自己关闭连接。注意密码作为一个hash参数传递,是因为SSH登录验证方式比较多,需要的参数变化多样。
如果不需要执行命令,仅仅是传输文件,可以使用Net::SCP.start,类似Net::SSH.start
Net::SCP.start( HOST, USER, :password => PASS ) do |scp| scp.upload!( 'c:/scp1.rb', '/home/oldsong/' ) scp.download!( '/home/oldsong/test.txt', 'c:/' ) end
Net::SSH.start( HOST, USER, :password => PASS ) do|ssh| logfiles = ssh.exec!( 'ls *.log' ).split logfiles.each do |l| ssh.scp.download!( l, l ) end end
Net::SSH.start( HOST, USER, :password => PASS ) do|ssh| ssh.scp.upload!( 'large.zip', '.' ) do|ch, name, sent, total| print "\r#{name}: #{(sent.to_f * 100 / total.to_f).to_i}%" end end
Net::SSH.start( HOST, USER, :password => PASS ) do|ssh| ssh.scp.download!( 'logs', '.', :recursive => true ) end
Net::SCP.start( HOST, USER, :password => PASS ) do|scp| puts scp.download!('log.txt').split(/\n/).grep(/^ERROR/) end
Net::SCP.start( HOST, USER, :password => PASS ) do|scp| sftp.upload!(f, remote_file) do |event, uploader, *args| case event # args[0] : file metadata when :open puts "start uploading.#{args[0].local} -> #{args[0].remote} #{args[0].size} bytes}" when :put then # args[0] : file metadata # args[1] : byte offset in remote file # args[2] : data being written (as string) puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}" when :close then # args[0] : file metadata puts "finished with #{args[0].remote}" when :mkdir then # args[0] : remote path name puts "creating directory #{args[0]}" when :finish then puts "all done!" end end puts "upload success" end