Ruby - 更新运行脚本

时间:2017-08-13 17:41:38

标签: ruby

是否有可能破坏当前运行的Ruby脚本,更新它,然后继续运行它?

E.g。说你有脚本:

(0..10).each do |x|
   puts x
end 

你可以打断它,修改它,以便读取第二行:

   puts x * 2

然后继续执行?

(假设我们忽略了像中断时间太短的琐碎参数)

2 个答案:

答案 0 :(得分:2)

如果您想实际停止该过程,可以trap中断信号,将当前进度写入文件,然后在开始备份时查找该文件:

$(function() {
  $(document).on("contextmenu", ".container", function(event) {
    // do stuff
  })
})

结果:

progress_file = './script_progress.txt'
x = if File.exists?(progress_file)
  File.read(progress_file).to_i
else
  0
end

Signal.trap("INT") {
  File.open(progress_file, 'w') { |f| f.write(x.to_s) }
  exit
}

while x <= 10 do
  puts x
  x += 1

  sleep(1)
end

您还可以在脚本退出时使用at_exit来编写文件(即使它刚刚正常完成):

$ rm script_progress.txt 
$ ruby example.rb 
0
1
2
3
^C$ cat script_progress.txt 
4
# modify example.rb here, changing `puts x` to `puts x * 2`
$ ruby example.rb 
8
10
12
14
16
18
20

结果:

progress_file = './script_progress.txt'
x = if File.exists?(progress_file)
  File.read(progress_file).to_i
else
  0
end

at_exit do
  File.open(progress_file, 'w') { |f| f.write(x.to_s) }
end

while x <= 10 do
  puts x
  x += 1

  sleep(1)
end

如果您希望流程继续运行,但只是为了能够在功能上切换不同,您可以使用Process.kill发送自定义信号:

$ ruby example.rb 
0
1
2
3
4
^Cexample.rb:16:in `sleep': Interrupt
    from example.rb:16:in `<main>'

# modify example.rb to double the output again 
$ ruby example.rb 
10
12
14
16
18
20

结果:

pid = fork do
  Signal.trap("USR1") {
    $double = !$double
  }

  (0..10).each do |x|
    puts $double ? x * 2 : x

    sleep(1)
  end
end

Process.detach(pid)
sleep(5)
Process.kill("USR1", pid)
sleep(6)

你可以用它来再次告诉ruby $ ruby example.rb 0 1 2 3 4 10 12 14 16 18 20 一个文件:

load

结果:

File.open('print_number.rb', 'w') do |file|
  file.write <<-contents
def print_number(x)
  puts x
end
contents
end

pid = fork do
  load './print_number.rb'
  Signal.trap("USR1") {
    load './print_number.rb'
  }

  (0..10).each do |x|
    print_number(x)

    sleep(1)
  end
end

Process.detach(pid)
sleep(5)
File.open('print_number.rb', 'w') do |file|
  file.write <<-contents
def print_number(x)
  puts x * 2
end
contents
end
Process.kill("USR1", pid)
sleep(6)

答案 1 :(得分:0)

pry做了类似的事情。

如果我有这样的脚本require 'pry' result = [] 5.times do |i| result << "#{i}" binding.pry if i == 2 end puts "result is ", result.join(",")

edit test.rb

然后在第3次迭代时,它会在断点处暂停,我可以输入命令。如果我输入

$EDITOR

然后edit(或nano)将打开,我可以更改源代码。当我退出文本编辑器时,pry将处于相同的断点,但是将使用修改后的代码重新运行现有代码。这是一种子shell,退出它将使用原始代码恢复原始断点。退出第二个断点后,我返回bash,我对该文件的编辑已被保留。

除了将路径传递给result << "#{i}" 之外,您还可以传递方法名称,但它具有相同的效果(子shell)。所以在任何一种情况下,使用上面的代码,如果我改变了

result << "#{i}*"

result is 0,1,2,3,4

,我会看到result is 0*,1*,2*,3*,4*result is 0,1,2,3*,4*,但不是require 'pry' a = 1 binding.pry puts a

此外,在pry中,可以在断点中轻松编辑局部变量。例如:

a = 2

如果我键入control+d然后2退出断点,则程序会按预期打印$( document ).ready(function() { var iAmProcessing = false; $('.link').click(function(){ if (iAmProcessing === true) { return; } iAmProcessing = true; $.post('ajax1.php?strana='+$(this).attr('strana'), function(odgovor) { iAmProcessing = false; $('#odgovor').html(odgovor); }); }); }); 。您还可以使用运行时元编程来覆盖方法,实例变量等。