我可以从Ruby中获得系统调用的连续输出吗?

时间:2011-03-04 13:54:12

标签: ruby bash scripting scp

当您在Ruby脚本中使用系统调用时,您可以获得该命令的输出:

output = `ls`
puts output

这就是this question的内容。

但有没有办法显示系统调用的连续输出?例如,如果运行此安全复制命令,则通过SSH从服务器获取文件:

scp user@someserver:remoteFile /some/local/folder/

...随着下载进度显示连续输出。但是这个:

output = `scp user@someserver:remoteFile /some/local/folder/`
puts output

...不捕获该输出。

如何从Ruby脚本中显示正在进行的下载进度?

5 个答案:

答案 0 :(得分:9)

尝试:

IO.popen("scp -v user@server:remoteFile /local/folder/").each do |fd|
  puts(fd.readline)
end

答案 1 :(得分:3)

我认为使用ruby标准库处理SCP会有更好的运气(而不是分支shell进程)。 Net :: SCP库(以及整个Net :: *库)功能齐全,与Capistrano一起使用来处理远程命令。

结帐http://net-ssh.rubyforge.org/了解可用内容。

答案 2 :(得分:2)

Tokland在我问的时候回答了这个问题,但是Adam的方法就是我最终使用的方法。这是我完成的脚本,执行显示已下载的字节数,以及完成的百分比。

require 'rubygems'
require 'net/scp'
puts "Fetching file"

# Establish the SSH session
ssh = Net::SSH.start("IP Address", "username on server", :password => "user's password on server", :port => 12345)

# Use that session to generate an SCP object
scp = ssh.scp

# Download the file and run the code block each time a new chuck of data is received
scp.download!("path/to/file/on/server/fileName", "/Users/me/Desktop/") do |ch, name, received, total|

  # Calculate percentage complete and format as a two-digit percentage
  percentage = format('%.2f', received.to_f / total.to_f * 100) + '%'

  # Print on top of (replace) the same line in the terminal
  # - Pad with spaces to make sure nothing remains from the previous output
  # - Add a carriage return without a line feed so the line doesn't move down
  print "Saving to #{name}: Received #{received} of #{total} bytes" + " (#{percentage})               \r"

  # Print the output immediately - don't wait until the buffer fills up
  STDOUT.flush
end

puts "Fetch complete!"

答案 3 :(得分:0)

你试过IO.popen吗? 您应该能够在进程仍在运行时读取输出并进行相应的解析。

答案 4 :(得分:0)

将stderr重定向到stdout可能对您有用:

output = `scp user@someserver:remoteFile /some/local/folder/ 2>&1`
puts output

那应该捕获stderr和stdout。你只能通过扔掉stdout来捕获stderr:

output = `scp user@someserver:remoteFile /some/local/folder/ 2>&1 >/dev/null`
puts output

然后,您可以使用IO.popen