Files
ubicloud/bin/restarter
Daniel Farina 2312aa35bb Prepend a newline to the restarter restart output
I've noticed that stderr from the child process and and restarter
stdout can get blended here, which is slightly surprising since
restarter waits until the child process has exited, i.e. it has closed
its file descriptors.

An example:

    /app/scheduling/dispatcher.rb:56:in `block in start_strand'{"restarter":{"start_time":"2025-03-23T14:58:57+00:00","command_exit":{"command":["bin/respirate"],"exitstatus":1,"pid":27,"success":false}}}

Perhaps there are situations where the subprocess doesn't flush a
trailing newline.

Since `restarter` doesn't (normally) run its loop so often,
defensively print an an extra newline so that things don't look quite
as weird in those cases.

You can see the newline in the output:

     $ RESTART_MINIMUM_TIME_ALIVE=10 bin/restarter bash -c 'sleep 1; echo hi; exit 1'
     {"restarter":{"start_time":"2025-03-25T17:56:23+00:00","startup":{"command":["bash","-c","sleep 1; echo hi; exit 1"],"minimum_time_alive":10}}}
     hi

     {"restarter":{"start_time":"2025-03-25T17:56:23+00:00","command_exit":{"command":["bash","-c","sleep 1; echo hi; exit 1"],"exitstatus":1,"pid":29308,"success":false}}}
     hi

     {"restarter":{"start_time":"2025-03-25T17:56:23+00:00","command_exit":{"command":["bash","-c","sleep 1; echo hi; exit 1"],"exitstatus":1,"pid":29311,"success":false}}}
     hi

     {"restarter":{"start_time":"2025-03-25T17:56:23+00:00","command_exit":{"command":["bash","-c","sleep 1; echo hi; exit 1"],"exitstatus":1,"pid":29314,"success":false}}}
     {"restarter":{"start_time":"2025-03-25T17:56:23+00:00","shutdown":{"command":["bash","-c","sleep 1; echo hi; exit 1"],"minimum_time_alive":10}}}

Which uses the same command/test methodology as
e5f9d83002.
2025-03-26 13:43:10 -07:00

50 lines
1.2 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# frozen_string_literal: true
minimum_time_alive = Integer(ENV.fetch("RESTART_MINIMUM_TIME_ALIVE", "3600"), 10)
require "json"
command = ARGV.dup.freeze
start_time = Time.now
iso_start = start_time.utc.strftime("%Y-%m-%dT%H:%M:%S%:z").freeze
puts JSON.generate(restarter: {
start_time: iso_start,
startup: {
command:,
minimum_time_alive:
}
})
loop do
system(*command)
status = $?
# Extra newline to prevent blending with subprocess just in
# case. Done as a separate system call, to be extra-accommodating to
# loggers that may want process things one system call at a time:
# below PIPE_BUF each write() matches with a read().
puts
puts JSON.generate(restarter: {
start_time: iso_start,
command_exit: {
command:,
exitstatus: status.exitstatus,
pid: status.pid,
success: status.success?
}
})
sleep(rand(1..10))
if Time.now - start_time > minimum_time_alive
puts JSON.generate(restarter: {start_time: iso_start,
shutdown: {
command:,
minimum_time_alive:
}})
exit
end
end