2011-08-04 5 views
2

入力と処理を2つの部分に分割して、プロンプトを指定する必要がないようにしました(wait_forなど)。問題はコマンドが受信されたが処理されなかったことである。チャネルプロセスはget_inputスレッドから呼び出されます(on_processでputsを出力します)が、何も起こりません。ruby​​ net/ssh channelが死ぬ?

は(on_processのみon_dataが呼び出された後、チャネルだけでアクティブに座っている?== trueこの時点ではまだ一度後と呼ばれている)

ENV['PATH'] = 'H:\mydocu~1\usrbin\ansi140\x86;' + ENV['PATH'] 
`ansicon.exe -p` 

require 'net/ssh' 

hostname = "server" 
username = "user" 
password = "password" 

@data = '' 
@print = true 
@cmd = '' 

#clear the log 
File.open('ssh_command.log', 'w') {|f| f.write('')} 


get_input = Thread.new { 
     while true 
     @cmd = nonblocking_stdin_gets 
     exit if @cmd.strip == "Q" 
     File.open('ssh_command.log', 'a+') { |f| f.write("{#{@cmd}}") } 
     if @cmd.rstrip != '' or @cmd =~ /\r?\n/ 
      puts "sending..." 
      @print = false 
      @openchannel.process 
     end 
     end 
    } 

if RUBY_PLATFORM =~ /win32/ 
    require 'Win32API' 
    $win32_console_kbhit = Win32API.new("msvcrt", "_kbhit", [], 'I') 
    def console_input_ready? 
    $win32_console_kbhit.call != 0 
    end 
    def nonblocking_stdin_gets 
    sleep(0.1) until console_input_ready? 
    $stdin.gets # don't bother to use getc, it also blocks until user hits <return> 
    end 
else 
    def nonblocking_stdin_gets 
    $stdin.gets # it just works, on unix 
    end 
end 

@openchannel = nil 

Net::SSH.start(hostname, username, :password => password) do |session| 

    @openchannel = session.open_channel do |channel| 

    channel.on_data do |ch, data| 
     @data += data 
    end 

    channel.on_extended_data do |ch, type, data| 
     puts "got stderr: #{data}" 
    end 

    channel.on_request "exit-status" do |ch, data| 
     puts "process terminated with exit status: #{data.read_long}" 
    end 

    channel.on_open_failed { |ch, code, desc| puts "err: #{desc}" } 

    # must come before shell 
    channel.request_pty :term => "xterm" do |ch, success| 
     if success 
     puts "pty successfully obtained" 
     else 
     puts "could not obtain pty" 
     end 
    end 

    channel.send_channel_request "shell" do |ch, success| 
     if success 
     puts "user shell started successfully" 
     else 
     puts "could not start user shell" 
     end 
    end 

    channel.on_eof do |ch| 
     puts "remote end is done sending data" 
    end 

    channel.on_close do |ch| 
     puts "channel is closing!" 
    end 

    channel.on_process do |ch| 
     print @data if @print 
     puts "command:#{@cmd}" 
     if @cmd.rstrip != '' or @cmd =~ /\r?\n/ 
     #system("cls") 
     channel.send_data(@cmd.rstrip + "\r\n") 
     @cmd = '' 
     @print = true 
     else 
     puts "no command" 
     end 
    end 

    end #channel_end 
    session.loop 
end #session_end 

答えて

3

はので、私はそれを考え出し、処理イベントがあるだけでデータが受信された後に実行し、SEND_DATAはだけなので、プロセスイベントが複数回実行されていることを確認するために、データキュー

に追加されます... この

session.loop(0.1) 
を追加