我希望在SSH会话中的远程计算机上工作:
使用我的脚本a可以执行步骤1和2。执行su命令时,我可以发送密码,得到我期待的答案(
on_data: data = gis@v04ree:~>
got gis@v04ree:~>
但是,那我该怎么办?我坐在我的频道上,没有任何反应。 如何让频道了解命令已经完成以及我想在远程机器上进行操作?
require 'net/ssh'
require 'net/sftp'
class Connection
def connect
host = 'host'
user = 'user'
#1. Login
Net::SSH.start(host, user) do |ssh|
puts ssh.exec!("whoami")
#2. su
begin
puts(su(ssh, "otherUser", "otherPwd"))
rescue Exception => e
puts e
end
#3. work
puts "logged in as " << ssh.exec!("whoami")
ssh.close
end
end
def su(ssh, user, pwd)
channel = ssh.open_channel do |ch|
channel.request_pty do |ch, success|
raise "Could not obtain pty (i.e. an interactive ssh session)" if !success
end
command = "su - #{user}\n"
puts "command = #{command}"
channel.exec command do |ch, success|
raise "could not execute command" unless success
# "on_data" is called when the process writes something to stdout
ch.on_data do |c, data|
puts "on_data: data = "+data
if data == "Password: "
puts "Password request"
channel.send_data "#{pwd}\n"
end
if data == "gis@v04ree:~> "
#logged in as gis
puts "got gis@v04ree:~>"
#and now? What's next?
#channel.eof! # <-doesn't work
ch.exec "ls" do |ch, success| #<- doesn't work either: success is false
unless success
puts "alas! the command could not be invoked!"
end
end
end
end
#wouldn't be called
ch.on_extended_data do |c, type, data|
puts "on_extended_data: data = #{data}"
end
end #end su - gis
#which statement
ssh.loop
#channel.wait
end
end
end #class end
Connection.new.connect
答案 0 :(得分:2)
问题是su
正在创建一个子shell,而net-ssh
正在控制最外层的shell。就像运行emacs
或来自net-ssh
的某些内容一样,您不能指望net-ssh
能够知道如何控制内壳。
所以你需要做的就是当你发现su
成功时,你必须发送数据就好像你只是输入它一样,然后你就可以阅读标准输出了。遗憾的是,您不能将stdout
与stderr
分开,因为它位于子shell中,但您仍然可以获得输出。
在成功ch.exec
之后,不使用su
,而是使用ch.send_data "command\n"
并阅读输出。不要忘记用ch.send_data "exit\n"
结束所有事情。 (请注意,\n
必须遵循每个命令来模拟控制台中的回车键