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

发布于 2024-10-20 04:47:56 字数 572 浏览 2 评论 0原文

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

output = `ls`
puts output

这就是 这个问题是关于。

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

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

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

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

...并没有捕获该输出。

如何从 Ruby 脚本内部显示下载的持续进度?

When you use a system call in a Ruby script, you can get the output of that command like this:

output = `ls`
puts output

That's what this question was about.

But is there a way to show the continuous output of a system call? For example, if you run this secure copy command, to get a file from a server over SSH:

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

... it shows continuous output with the progress of the download. But this:

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

... doesn't capture that output.

How can I show the ongoing progress of the download from inside my Ruby script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

拥有 2024-10-27 04:47:56

尝试:

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

Try:

IO.popen("scp -v user@server:remoteFile /local/folder/").each do |fd|
  puts(fd.readline)
end
冷弦 2024-10-27 04:47:56

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

查看 http://net-ssh.rubyforge.org/ 了解可用内容的概要。

I think you would have better luck using the ruby standard library to handle SCP (as opposed to forking a shell process). The Net::SCP library (as well as the entire Net::* libraries) are full featured and used with Capistrano to handle remote commands.

Checkout http://net-ssh.rubyforge.org/ for a rundown of what is available.

寒尘 2024-10-27 04:47:56

托克兰回答了我提出的问题,但我最终使用了亚当的方法。这是我完成的脚本,它确实显示下载的字节数,以及完成的百分比。

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

Tokland answered the question as I asked it, but Adam's approach was what I ended up using. Here was my completed script, which does show a running count of bytes downloaded, and also a percentage complete.

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!"
慢慢从新开始 2024-10-27 04:47:56

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

have you tried with IO.popen ?
you should be able to read the output while the process is still running and parse it accordingly.

夜无邪 2024-10-27 04:47:56

将 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。

Redirecting stderr to stdout may work for you:

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

That should capture both stderr and stdout. You can capture stderr only by throwing away stdout:

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

You can then use IO.popen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文