Ruby - update running script

Is it possible to break the current Ruby script, update it and continue its execution?

eg. let's say you had a script:

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

You could interrupt it, change it so that the second line reads:

   puts x * 2

then continue execution?

(assuming we ignore trivial arguments like interrupt time is too short)

+4
source share
2 answers

If you want to stop the process, you can trapinterrupt the signal, write the current progress to a file, and then find this file when starting the backup:

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

Result:

$ 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

You can also use at_exitto write the file at any time when the script exits (even if it just ends normally):

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

Result:

$ 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

, , , Process.kill:

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 example.rb 
0
1
2
3
4
10
12
14
16
18
20

, ruby ​​ 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)

:

$ ruby example.rb 
0
1
2
3
4
10
12
14
16
18
20
+2

pry - .

script test.rb, :

require 'pry'

result = []
5.times do |i|
  result << "#{i}"
  binding.pry if i == 2
end

puts "result is ", result.join(",")

3- , .

edit test.rb

$EDITOR ( nano), . , pry , , . -, . bash, .

edit , (-). ,

result << "#{i}"

to

result << "#{i}*"

result is 0,1,2,3,4, result is 0*,1*,2*,3*,4*, result is 0,1,2,3*,4*.

, pry . :

require 'pry'

a = 1
binding.pry
puts a

a = 2, control+d, , 2, . , , ..

0

Source: https://habr.com/ru/post/1683622/


All Articles