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.
70 lines
1.6 KiB
Ruby
Executable File
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
|