【问题标题】:Can I get continuous output from system calls in Ruby?我可以从 Ruby 中的系统调用中获得连续输出吗?
【发布时间】:2011-07-08 20:29:04
【问题描述】:

当您在 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 脚本中显示下载的持续进度?

【问题讨论】:

  • 你这里有两个正交问题,因为 scp 默认只输出到终端,你需要 scp -v
  • @tokland - 让它输出调试消息,但不是我单独运行 scp 时看到的传输进度。我认为那些不能去标准输出,我没有看到 scp 将它们发送到那里的选项。
  • 显然 scp 将进度信息发送到“交互式终端”?不知道如何捕捉...

标签: ruby bash scripting scp


【解决方案1】:

试试:

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

【讨论】:

  • 这适用于获取标准输出消息,但似乎这不是 scp 发送其传输进度的地方。所以我想我现在的问题是 scp。
  • 这回答了我提出的问题 - scp 不进行正常输出的事实被证明是一个意想不到的细节。
  • 请参阅下面的答案,了解我是如何从 Ruby 标准库中获得该输出的。
【解决方案2】:

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

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

【讨论】:

【解决方案3】:

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!"

【讨论】:

  • 是的,这是最好的方法,因为使用好的语言只有依赖它们的库才是合乎逻辑的。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

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

    这应该同时捕获标准错误和标准输出。您只能通过丢弃 stdout 来捕获 stderr:

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

    然后您可以使用IO.popen

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      • 2019-11-13
      • 2013-03-18
      • 1970-01-01
      • 2023-03-14
      • 2011-12-02
      • 2020-03-08
      相关资源
      最近更新 更多