Ruby,通过 SSH 和 LOG 逐一运行 linux 命令
我想用 Ruby 女巫 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
例如,如果我想在远程linux上创建新文件夹和文件:“./verylongdirname/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
运行上面的代码后,我将在#1、#2、#3、#4、#5 行中获得有关执行命令的完整 LOG 信息。问题是Linux上的状态,在cmds数组中执行命令之间,没有被保存(所以我必须在运行正确的命令之前重复“cd”语句)。我对此并不满意。
我的目的是拥有这样的 cmd 表:
cmds=["mkdir verylongdirname", \ #1
"cd verylongdirname", \
"mkdir anotherlongdirname", \ #2
"cd anotherlongdirname", \
"touch a.txt", \ #3
"ls -la", \ #4
"find ./ firefox"] #5
如您所见,运行每个命令之间的状态保存在 Linux 计算机上(并且在运行正确的命令之前我们不需要重复适当的“cd”语句)。如何更改“rs(ssh,cmds)”程序来执行此操作并像以前一样记录所有内容(comand、stdout、stdin)?
I want to write code in Ruby witch net::ssh that run commands one by one on remote linux machine and log everything (called command, stdout and stderr on linux machine).
So I write function:
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
For example if I want to create on remote linux new folders and file: "./verylongdirname/anotherlongdirname/a.txt", and list files in that direcotry, and find firefox there (which is stupid a little :P) so i call above procedure like that:
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
After run code above i will have full LOG witch informations about executions commands in line #1,#2,#3,#4,#5. The problem is that state on linux, between execude commands from cmds array, is not saved (so I must repeat "cd" statement before run proper command). And I'm not satisfy with that.
My purpose is to have cmds tables like that:
cmds=["mkdir verylongdirname", \ #1
"cd verylongdirname", \
"mkdir anotherlongdirname", \ #2
"cd anotherlongdirname", \
"touch a.txt", \ #3
"ls -la", \ #4
"find ./ firefox"] #5
As you see, te state between run each command is save on the linux machine (and we don't need repeat apropriate "cd" statement before run proper command). How to change "rs(ssh,cmds)" procedure to do it and LOG EVERYTHING (comand,stdout,stdin) like before?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(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/
示例:
即
Net::SSH::Telnet
是同步的,并保留状态,因为它与远程设备一起在 pty 中运行外壳环境。请记住设置正确的提示检测,否则一旦您调用Net::SSH::Telnet
,它就会显示为挂起(它正在尝试查找提示)。Perhaps try it with an ssh channel instead to open a remote shell. That should preserve state between your commands as the connection will be kept open:
http://net-ssh.github.com/ssh/v1/chapter-5.html
Here's also an article of doing something similar with a little bit different approach:
http://drnicwilliams.com/2006/09/22/remote-shell-with-ruby/
Edit 1:
Ok. I see what you are saying.
SyncShell
was removed from Net::SSH 2.0. However I found this, which looks like it does pretty much whatSyncShell
did:http://net-ssh-telnet.rubyforge.org/
Example:
I.e.
Net::SSH::Telnet
is synchronous, and preserves state, because it runs in a pty with your remote shell environment. Remember to set the correct prompt detection, otherwiseNet::SSH::Telnet
will appear to hang once you call it (it's trying to find the prompt).您可以使用管道代替:
You can use pipe instead:
好吧,最后在 @Casper 的帮助下我得到了程序(也许有人使用它):
我们用代码调用它:
谢谢,再见。
Ok, finally with the help of @Casper i get the procedure (maby someone use it):
And we call it in code:
Thanks, bye.
这是 Net/ssh 的包装,这是文章 http://ruby-lang.info/blog /virtual-file-system-b3g
源 https://github.com/alexeypetrushin/vfs
记录所有命令只需覆盖 Box.bash 方法并在那里添加日志记录
Here's wrapper around Net/ssh here's article http://ruby-lang.info/blog/virtual-file-system-b3g
source https://github.com/alexeypetrushin/vfs
to log all commands just overwrite the Box.bash method and add logging there