我正在尝试学习如何使用net-ssh gem for ruby。在我登录到目录- /home/james之后,我想执行以下命令。
cd /
pwd
ls当我对putty执行此操作时,它可以工作,并且我可以看到一个目录列表。但是,当我用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。这是它在putty中的工作方式。ruby代码中的错误是什么?
发布于 2015-03-02 06:36:35
似乎每个命令都在它自己的环境中运行,所以当前目录不会从exec转移到exec。如果您执行以下操作,则可以验证这一点:
exec('cd / && pwd', conn)
它将打印/。文档中并不清楚如何使所有命令在同一环境中执行,也不清楚这是否可能。
发布于 2015-03-02 06:37:46
这是因为net/ssh是无状态的,所以每次执行命令时它都会打开一个新的连接。您可以使用实现解决此问题的rye gem。但我不知道它是否适用于ruby > 2,因为它的开发不是那么活跃。
另一种方法是使用pty进程,在该进程中,您将使用ssh命令打开一个伪终端,然后使用输入和输出文件为该终端编写命令并读取结果。要读取结果,需要使用IO类的select方法。但是你需要学习如何使用这些实用程序,因为对于一个没有经验的程序员来说,这并不是那么明显。
发布于 2015-03-02 15:22:36
而且,耶,我发现了如何做到这一点,事实上,它是如此简单。我想我上一次没有得到这个解决方案,因为我对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 == "exit\n"
end
end
threads.each(&:join)我们在这里,一个使用net-ssh ruby gem的交互式终端。有关更多信息,请查看here its的前一个版本1,但它对您了解每个部件是如何工作的非常有用。和here
https://stackoverflow.com/questions/28799593
复制相似问题