Files
ubicloud/rhizome/common/bin/daemonizer
Daniel Farina 713d4ba591 Make daemonizer --clean idempotent
Because a previous `daemonizer --clean` may not be recorded by the
label that called it (e.g. database connection drops, deadlock
detector kills the transaction, whatever) it's necessary to assume a
`dead` unit has already been cleaned.
2025-02-14 06:58:15 -08:00

75 lines
1.7 KiB
Ruby
Executable File

#!/bin/env ruby
# frozen_string_literal: true
require "fileutils"
require_relative "../lib/util"
if ARGV.count != 2
fail "Wrong number of arguments. Expected 2, Given #{ARGV.count}"
end
STATE_MAP = {
"dead" => "NotStarted",
"running" => "InProgress",
"exited" => "Succeeded",
"failed" => "Failed"
}
def get_state(name)
state = r("systemctl show -p SubState --value #{name}.service").chomp
STATE_MAP[state] || "Unknown"
end
def clean(name)
state = get_state(name)
case state
when "InProgress", "Unknown"
fail "Cannot clean unless the service is in Succeeded or Failed state!"
when "NotStarted"
# no-op, can occur if a previous clean was run but transition
# recording that it ran could not commit.
when "Succeeded"
r "sudo systemctl stop #{name}.service"
when "Failed"
r "sudo systemctl reset-failed #{name}.service"
end
end
if ARGV[0] == "--check"
name = ARGV[1]
print(get_state(name))
elsif ARGV[0] == "--clean"
name = ARGV[1]
clean(name)
else
command = ARGV[0]
name = ARGV[1]
FileUtils.mkdir_p("var/log")
FileUtils.mkdir_p("var/proc")
File.open("var/proc/#{name}.lock", File::RDWR | File::CREAT) do |f|
break unless f.flock(File::LOCK_EX | File::LOCK_NB)
state = get_state(name)
case state
when "InProgress", "Unknown"
break
when "Succeeded", "Failed"
clean(name)
end
dir = Dir.pwd
stdin = $stdin.read
if stdin != ""
safe_write_to_file("var/proc/#{name}.stdin", stdin)
command = "#{command} < #{dir}/var/proc/#{name}.stdin"
end
command = "/bin/bash -c '#{command} > #{dir}/var/log/#{name}.stdout 2> #{dir}/var/log/#{name}.stderr'"
r "sudo systemd-run --working-directory #{dir} --unit #{name} --remain-after-exit #{command}"
end
end