我有一些Ruby脚本用于自动执行一些可能需要很长时间才能完成的rsync任务。我使用popen
来运行命令:
def process(command)
io = IO.popen(command)
output = io.read
io.close
return output
end
该命令由Sinatra app中的get请求执行:
get '/sync' do
stream do |out|
rsync_command = "rsync somedir"
out << process(rsync_command)
end
end
然后我在前端使用Ajax请求访问输出:
$.get('/sync', function (data) {
console.log(data);
});
是否可以显示shell输出,而不是仅在过程结束时返回?
答案 0 :(得分:0)
IO :: POPEN:
将指定的命令作为子进程运行;子流程的标准 输入和输出将连接到返回的IO对象。
stdout是一个文件。你告诉ruby用行io.read
读取整个文件,因此ruby必须等到文件结束才能返回文本,这发生在另一端关闭管道时,即当目标程序时已完成执行。您不必一次读取文件整个文件,而是可以逐行读取文件:
def process(command)
IO.popen(command) do |io|
io.each do |line|
puts line
end
end
end
告诉ruby在找到换行符之前读取文件,然后返回文本......一遍又一遍地获取文件,直到文件结束。
以下是一个完整的例子:
#my_prog.rb
text = ""
1.upto(10) do
text << "."
puts text
STDOUT.flush
sleep 1
end
...
def process(command)
IO.popen(command) do |io|
io.each do |line|
puts line
end
end
end
my_command = 'ruby ./my_prog.rb'
process(my_command)
请注意,除非目标程序刷新输出,否则输出将缓冲,因此在填充缓冲区之前,文本将无法读取(此时缓冲区将自动刷新)或目标程序结束(此时缓冲区也将自动刷新)。您可以只使用程序顶部的行STDOUT.flush()
,而不是反复调用STDOUT.sync = true
。当sync设置为true时,ruby不会缓冲输出。
答案 1 :(得分:-1)
IO.popen(command){ |f| puts f.lines.to_a }