Files
ubicloud/rhizome/common/bin/daemonizer2
mohi-kalantari 496ebc92e9 Introduce daemonizer2 for better log handling and supporting argv
With the new version, we will not store the systemd unit logs in file
and instead rely on journalctl. This way the logs of last tries would
not get deleted.

Locking system used in the version 1 is also deleted since the unit name
is enough for locking purposes.

Stdin is also written to /dev/shm which is a filesystem on top of memory
which is faster and files are deleted on reboot; increasing performance
and security

Also in the new version, we can specify argv arguments instead of
putting the whole command in single quotes.

Unit name is now the second argv instead of the last. it was done because
it was always a single word and we could position is somewhere static

This is an example of version 1:

vm.sshable.cmd("common/bin/daemonizer 'sleep infinity' test_daemonizer")

This is an example of version2:

vm.sshable.cmd("common/bin/daemonizer2 run test_daemonizer2 sleep infinity")

The first parameter is used as the command name. there will be no -- in
daemonizer2 API and instead "clean" or "check" would be used. Also in order
to keep the style consistent, "run" command will be used to spawn up new units.

the second parameter would be used as the name and all the other parameters
would be used in the original script.
2025-04-10 12:17:47 +02:00

70 lines
1.6 KiB
Ruby
Executable File

#!/bin/env ruby
# frozen_string_literal: true
require "fileutils"
require "shellwords"
require_relative "../lib/util"
if ARGV.count < 2
fail "Wrong number of arguments. Expected at least 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, stdin_path)
state = get_state(name)
begin
case state
when "InProgress", "Unknown", "NotStarted"
fail "Cleanup is only allowed when the service is in a Succeeded, Failed, or NotStarted state"
when "Succeeded"
r "sudo systemctl stop #{name}.service"
when "Failed"
r "sudo systemctl reset-failed #{name}.service"
end
ensure
begin
File.unlink(stdin_path)
rescue Errno::ENOENT
end
end
end
command = ARGV[0]
name = ARGV[1]
stdin_path = "/dev/shm/#{name}.stdin"
case command
when "check"
print(get_state(name))
when "clean"
clean(name, stdin_path)
when "run"
command_parts = ARGV[2..]
state = get_state(name)
clean(name, stdin_path) if %w[Succeeded Failed].include?(state)
dir = Dir.pwd
stdin = $stdin.read.strip
if stdin.empty?
command = Shellwords.shelljoin(command_parts)
else
safe_write_to_file(stdin_path, stdin)
command = "cat #{stdin_path} | " + Shellwords.shelljoin(command_parts)
end
r "sudo systemd-run --working-directory #{dir} --unit #{name} --remain-after-exit /bin/bash -c #{Shellwords.escape(command)}"
else
raise "Unknown command #{command}"
end