Ruby,通过SSH和LOG一切一个接一个地运行linux命令

Kam*_*ski 8 ruby ssh logging command sequential

我想在Ruby witch net :: ssh中编写代码,在远程linux机器上逐个运行命令并记录所有内容(在linux机器上称为命令,stdout和stderr).

所以我写函数:

  def rs(ssh,cmds)
    cmds.each do |cmd|
      log.debug "[SSH>] #{cmd}"
      ssh.exec!(cmd) do |ch, stream, data|    
        log.debug "[SSH:#{stream}>] #{data}"            
      end  
    end
  end
Run Code Online (Sandbox Code Playgroud)

例如,如果我想在远程linux上创建新的文件夹和文件:"./ everylongdirname/anotherlongdirname/a.txt",并在该目录中列出文件,并在那里找到firefox(这是愚蠢的一点:P)所以我打电话以上程序是这样的:

Net::SSH.start(host, user, :password => pass) do |ssh|  

  cmds=["mkdir verylongdirname", \                                 #1
        "cd verylongdirname; mkdir anotherlongdirname, \           #2
        "cd verylongdirname/anotherlongdirname; touch a.txt", \    #3
        "cd verylongdirname/anotherlongdirname; ls -la", \         #4
        "cd verylongdirname/anotherlongdirname; find ./ firefox"   #5 that command send error to stderr.
        ]

  rs(ssh,cmds)   # HERE we call our function

  ssh.loop
end
Run Code Online (Sandbox Code Playgroud)

在运行上面的代码之后,我将获得有关第1行,第2行,第3行,第4行,第5行中执行命令的完整LOG巫婆信息.问题是linux上的状态,来自cmds数组的执行命令之间没有保存(所以我必须在运行正确的命令之前重复"cd"语句).而且我对此并不满意.

我的目的是拥有像这样的cmds表:

  cmds=["mkdir verylongdirname", \     #1
        "cd verylongdirname", \        
        "mkdir anotherlongdirname", \  #2
        "cd anotherlongdirname", \
        "touch a.txt", \               #3
        "ls -la", \                    #4
        "find ./ firefox"]             #5
Run Code Online (Sandbox Code Playgroud)

如你所见,运行每个命令之间的状态是保存在linux机器上(并且在运行正确的命令之前我们不需要重复适当的"cd"语句).如何改变"rs(ssh,cmds)"程序来做它和LOG EVERYTHING(comand,stdout,stdin)之前一样?

Cas*_*per 4

也许尝试使用 ssh 通道来打开远程 shell。这应该保留命令之间的状态,因为连接将保持打开状态:

http://net-ssh.github.com/ssh/v1/chapter-5.html

这里还有一篇文章用稍微不同的方法做类似的事情:

http://drnicwilliams.com/2006/09/22/remote-shell-with-ruby/

编辑1

好的。我明白你在说什么。SyncShell已从 Net::SSH 2.0 中删除。然而我发现了这个,它看起来几乎做了什么SyncShell

http://net-ssh-telnet.rubyforge.org/

例子:

s = Net::SSH.start(host, user)
t = Net::SSH::Telnet.new("Session" => s, "Prompt" => %r{^myprompt :})
puts t.cmd("cd /tmp")  
puts t.cmd("ls")       # <- Lists contents of /tmp
Run Code Online (Sandbox Code Playgroud)

IeNet::SSH::Telnet是同步的,并且保留状态,因为它与远程 shell 环境一起在 pty 中运行。请记住设置正确的提示检测,否则Net::SSH::Telnet一旦调用它就会出现挂起(它正在尝试查找提示)。