Unix命令在服务器上工作,但不在ruby ssh会话中

我正在尝试学习如何使用net-ssh gem进行ruby。 在登录到目录 - / home / james后,我想执行下面的命令。

cd /
pwd
ls

当我用腻子做到这一点时,它可以工作,我可以看到目录列表。 但是,当我用ruby代码做它时,它不会给我相同的输出。

require 'rubygems' 
require 'net/ssh'

host = 'server'
user = 'james'
pass = 'password123'

def get_ssh(host, user, pass)
    ssh = nil
    begin
        ssh = Net::SSH.start(host, user, :password => pass)
        puts "conn successful!"
    rescue
        puts "error - cannot connect to host"
    end
    return ssh
end

conn = get_ssh(host, user, pass)

def exec(linux_code, conn)
    puts linux_code
    result = conn.exec!(linux_code)
    puts result
end

exec('cd /', conn)
exec('pwd', conn)
exec('ls', conn)

conn.close

输出 -

conn successful!
cd /
nil
pwd
/home/james
ls
nil

我期待pwd给我/而不是/ home / james。 这就是它在腻子中的工作原理。 Ruby代码中的错误是什么?


似乎每个命令都运行在它自己的环境中,所以当前目录不会从exec到exec。 如果你这样做,你可以验证这一点:

exec('cd / && pwd', conn)

它将打印/ 。 从文档中不清楚如何使所有的命令在相同的环境中执行,或者甚至可以完成。


这是因为net/ssh是无状态的,所以它会为每个命令执行打开一个新的连接。 您可以使用实现此功能的黑麦宝石。 但我不知道它是否适用于ruby> 2,因为它的发展并不那么活跃。

另一种方法是使用pty进程,在该进程中,您将使用ssh命令打开一个伪终端,而不是使用输入和输出文件为终端编写命令并读取结果。 要读取结果,您需要使用IO类的select方法。 但是你需要学习如何使用这些工具,因为它对于一个没有经验的程序员来说并不那么明显。


而且,我发现了如何去做,事实上它非常简单。 我想我上次没有得到这个解决方案,因为我对net-ssh,pty终端这个东西有点新。 但是,我终于找到了它,并且在这里和范例中。

require 'net/ssh'

shell = {} #this will save the open channel so that we can use it accross threads
threads = []
# the shell thread
threads << Thread.new do
  # Connect to the server
  Net::SSH.start('localhost', 'your_user_name', password: 'your_password') do |session|
    # Open an ssh channel
    session.open_channel do |channel|   
      # send a shell request, this will open an interactive shell to the server 
      channel.send_channel_request "shell" do |ch, success|    
        if success      
          # Save the channel to be used in the other thread to send commands
          shell[:ch] = ch
          # Register a data event
          # this will be triggered whenever there is data(output) from the server
          ch.on_data do |ch, data|
              puts data
          end  
        end  
      end  
    end  
  end  
end

# the commands thread
threads << Thread.new do
  loop do
    # This will prompt for a command in the terminal
    print ">"
    cmd = gets
    # Here you've to make sure that cmd ends with 'n'
    # since in this example the cmd is got from the user it ends with 
    #a trailing eol
    shell[:ch].send_data cmd
    # exit if the user enters the exit command
    break if cmd == "exitn"
  end
end

threads.each(&:join)

在这里,我们是一个使用net-ssh ruby​​ gem的交互式终端。 欲了解更多信息,请查看它以前的版本1,但它对你了解每件作品的用途非常有用。 和这里

链接地址: http://www.djcxy.com/p/4309.html

上一篇: Unix commands work on server but not in ruby ssh session

下一篇: Git reset = fatal: unable to read tree