首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Unix命令在服务器上有效,但在ruby ssh会话中无效

Unix命令在服务器上有效,但在ruby ssh会话中无效
EN

Stack Overflow用户
提问于 2015-03-02 05:55:13
回答 3查看 1.3K关注 0票数 1

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

代码语言:javascript
复制
cd /
pwd
ls

当我对putty执行此操作时,它可以工作,并且我可以看到一个目录列表。但是,当我用ruby代码做这件事时,它不会给我同样的输出。

代码语言:javascript
复制
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

输出-

代码语言:javascript
复制
conn successful!
cd /
nil
pwd
/home/james
ls
nil

我原以为pwd会给我/而不是/home/james。这是它在putty中的工作方式。ruby代码中的错误是什么?

EN

回答 3

Stack Overflow用户

发布于 2015-03-02 06:36:35

似乎每个命令都在它自己的环境中运行,所以当前目录不会从exec转移到exec。如果您执行以下操作,则可以验证这一点:

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

它将打印/。文档中并不清楚如何使所有命令在同一环境中执行,也不清楚这是否可能。

票数 3
EN

Stack Overflow用户

发布于 2015-03-02 06:37:46

这是因为net/ssh是无状态的,所以每次执行命令时它都会打开一个新的连接。您可以使用实现解决此问题的rye gem。但我不知道它是否适用于ruby > 2,因为它的开发不是那么活跃。

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

票数 1
EN

Stack Overflow用户

发布于 2015-03-02 15:22:36

而且,耶,我发现了如何做到这一点,事实上,它是如此简单。我想我上一次没有得到这个解决方案,因为我对net-ssh,pty终端这个东西有点陌生。但是,是的,我最终找到了它,在这里和例子。

代码语言:javascript
复制
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 == "exit\n"
  end
end

threads.each(&:join)

我们在这里,一个使用net-ssh ruby gem的交互式终端。有关更多信息,请查看here its的前一个版本1,但它对您了解每个部件是如何工作的非常有用。和here

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28799593

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档