2010-08-02 6 views
30

Ben sadece başarısız olması halinde, bir uzak sunucuda bir komut dosyası yürütmeye çalışırken, bir kod parçası var, bir takip çağrısı yapmak istiyorum, bu hayal edin:Ruby's Net :: SSH kütüphanesi ile çıkış durumu nasıl alınır?

require 'rubygems' 
require 'net/ssh' 
require 'etc' 

server = 'localhost' 

Net::SSH.start(server, Etc.getlogin) do |ssh| 
    puts (ssh.exec("true") ? 'Exit Success' : "Exit Failure") 
    puts (ssh.exec("false") ? 'Exit Success' : "Exit Failure") 
end 

I (stdout ve stderr'ın benim örneğimde yazıldığını görmezden gelir) - ama ilk satırın Ruby'nin false olarak çalışmasını beklediğim 0 ile çıkması ve "Çıkış Hatası" nı göstermesi (yani mantığın yanlış olması, üçüncül ihtiyaçlar) ters çevrilecek) - ama ikinci satırın karşıt durumdan çıkması gerekiyor ve değil.

Bu belgede, bunu nasıl yapacağım konusunda hiçbir şey bulamıyorum ve yanlış yaptığımdan endişeleniyorum.

cevap

66

Net :: SSH ile aşağıdaki işlem yöntemlerini çok daha kullanışlı buluyorum. Size farklı stdout ve stderr, exit code ve exit signal sağlar.

require 'rubygems' 
require 'net/ssh' 
require 'etc' 

server = 'localhost' 

def ssh_exec!(ssh, command) 
    stdout_data = "" 
    stderr_data = "" 
    exit_code = nil 
    exit_signal = nil 
    ssh.open_channel do |channel| 
    channel.exec(command) do |ch, success| 
     unless success 
     abort "FAILED: couldn't execute command (ssh.channel.exec)" 
     end 
     channel.on_data do |ch,data| 
     stdout_data+=data 
     end 

     channel.on_extended_data do |ch,type,data| 
     stderr_data+=data 
     end 

     channel.on_request("exit-status") do |ch,data| 
     exit_code = data.read_long 
     end 

     channel.on_request("exit-signal") do |ch, data| 
     exit_signal = data.read_long 
     end 
    end 
    end 
    ssh.loop 
    [stdout_data, stderr_data, exit_code, exit_signal] 
end 

Net::SSH.start(server, Etc.getlogin) do |ssh| 
    puts ssh_exec!(ssh, "true").inspect 
    # => ["", "", 0, nil] 

    puts ssh_exec!(ssh, "false").inspect 
    # => ["", "", 1, nil] 

end 

Bu yardımcı olur umarım. flitzwald tarafından yanıta

+0

Vay, bu serin Net :: SSH (Yakut 1.9+) içine bu benim versiyonunu yamalı ettik. Teşekkürler. – sarnold

+0

flitzwald, bu harika - Keşke retrospektif olarak bir ödül veya bir şey ekleyebilirdim! Çok teşekkürler! –

+0

Çok teşekkür ederim. Mükemmel çalışıyor. Bu Net :: SSH olmalıdır. –

6

Bina - Ben maymun

class Net::SSH::Connection::Session 
    class CommandFailed < StandardError 
    end 

    class CommandExecutionFailed < StandardError 
    end 

    def exec_sc!(command) 
    stdout_data,stderr_data = "","" 
    exit_code,exit_signal = nil,nil 
    self.open_channel do |channel| 
     channel.exec(command) do |_, success| 
     raise CommandExecutionFailed, "Command \"#{command}\" was unable to execute" unless success 

     channel.on_data do |_,data| 
      stdout_data += data 
     end 

     channel.on_extended_data do |_,_,data| 
      stderr_data += data 
     end 

     channel.on_request("exit-status") do |_,data| 
      exit_code = data.read_long 
     end 

     channel.on_request("exit-signal") do |_, data| 
      exit_signal = data.read_long 
     end 
     end 
    end 
    self.loop 

    raise CommandFailed, "Command \"#{command}\" returned exit code #{exit_code}" unless exit_code == 0 

    { 
     stdout:stdout_data, 
     stderr:stderr_data, 
     exit_code:exit_code, 
     exit_signal:exit_signal 
    } 
    end 
end 
+0

Bunu bir yama yayın akışı olarak göndermeyi düşündünüz mü? –

+0

Şu anda bu işleve dayanan bir proje üzerinde çalışıyorum - test edildikten sonra yapacağım. Çıkış kodunun başarılı bir şekilde çalıştırılmasına rağmen> 0 olduğu durumlar vardır, bu yüzden isteğe bağlı olarak yükseltmeyi değiştireceğim. – Mikey

+0

@Mikey Hangi durumlar olurdu? Kabuk, ssh veya kütüphane iletişimi problemi dışında sıfır olmayan bir çıkış kodu var mı yoksa komut, nonzro çıkış kodunu döndürür, ancak işini yaptı mı? – Phillipp