2017-12-04 10:17:46 +00:00
|
|
|
require 'set'
|
|
|
|
require 'open3'
|
|
|
|
|
|
|
|
@dry_run = ENV['DRY_RUN']
|
|
|
|
@verbose = ENV['VERBOSE']
|
|
|
|
|
|
|
|
UnitsDir = 'home-files/.config/systemd/user'
|
|
|
|
|
|
|
|
# 1. Stop all services from the old generation that are not present in the new generation.
|
|
|
|
# 2. Ensure all services from the new generation that are wanted by active targets are running:
|
|
|
|
# - Start services that are not already running.
|
|
|
|
# - Restart services whose unit config files have changed between generations.
|
|
|
|
# 3. If any services were (re)started, wait 'start_timeout_ms' and report services
|
|
|
|
# that failed to start. This helps debugging quickly failing services.
|
|
|
|
#
|
|
|
|
# Whenever service failures are detected, show the output of
|
2018-05-09 14:22:02 +00:00
|
|
|
# 'systemd --user status' for the affected services.
|
2017-12-04 10:17:46 +00:00
|
|
|
#
|
|
|
|
def setup_services(old_gen_path, new_gen_path, start_timeout_ms_string)
|
|
|
|
start_timeout_ms = start_timeout_ms_string.to_i
|
|
|
|
|
|
|
|
old_units_path = File.join(old_gen_path, UnitsDir) unless old_gen_path.empty?
|
|
|
|
new_units_path = File.join(new_gen_path, UnitsDir)
|
|
|
|
|
|
|
|
old_services = get_services(old_units_path)
|
|
|
|
new_services = get_services(new_units_path)
|
|
|
|
|
|
|
|
exit if old_services.empty? && new_services.empty?
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
all_services = get_active_targets_units(new_units_path)
|
|
|
|
maybe_changed = all_services & old_services
|
|
|
|
changed_services = get_changed_services(old_units_path, new_units_path, maybe_changed)
|
|
|
|
unchanged_oneshots = get_oneshot_services(maybe_changed - changed_services)
|
|
|
|
|
2018-05-09 14:22:02 +00:00
|
|
|
# These services should be running when this script is finished
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
services_to_run = all_services - unchanged_oneshots
|
2017-12-04 10:17:46 +00:00
|
|
|
|
|
|
|
# Only stop active services, otherwise we might get a 'service not loaded' error
|
|
|
|
# for inactive services that were removed in the current generation.
|
|
|
|
to_stop = get_active_units(old_services - new_services)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
to_restart = changed_services
|
2017-12-04 10:17:46 +00:00
|
|
|
to_start = get_inactive_units(services_to_run - to_restart)
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
raise "daemon-reload failed" unless run_cmd('systemctl', '--user', 'daemon-reload')
|
2017-12-04 10:17:46 +00:00
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
# Exclude units that shouldn't be (re)started or stopped
|
2019-04-14 00:04:52 +00:00
|
|
|
no_manual_start, no_manual_stop, no_restart = get_restricted_units(to_stop + to_restart + to_start)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
notify_skipped_units(to_restart & no_restart)
|
|
|
|
to_stop -= no_manual_stop
|
2019-04-14 00:04:52 +00:00
|
|
|
to_restart -= no_manual_stop + no_manual_start + no_restart
|
2017-12-04 10:17:46 +00:00
|
|
|
to_start -= no_manual_start
|
|
|
|
|
|
|
|
if to_stop.empty? && to_start.empty? && to_restart.empty?
|
|
|
|
print_service_msg("All services are already running", services_to_run)
|
|
|
|
else
|
|
|
|
puts "Setting up services" if @verbose
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
systemctl_action('stop', to_stop)
|
|
|
|
systemctl_action('start', to_start)
|
|
|
|
systemctl_action('restart', to_restart)
|
2017-12-04 10:17:46 +00:00
|
|
|
started_services = to_start + to_restart
|
|
|
|
if start_timeout_ms > 0 && !started_services.empty? && !@dry_run
|
|
|
|
failed = wait_and_get_failed_services(started_services, start_timeout_ms)
|
|
|
|
if failed.empty?
|
|
|
|
print_service_msg("All services are running", services_to_run)
|
|
|
|
else
|
|
|
|
puts
|
|
|
|
puts "Error. These services failed to start:", failed
|
|
|
|
show_failed_services_status(failed)
|
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_services(dir)
|
|
|
|
services = get_service_files(dir) if dir && Dir.exists?(dir)
|
|
|
|
Set.new(services)
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_service_files(dir)
|
2020-03-02 19:33:20 +00:00
|
|
|
Dir.chdir(dir) { Dir['*[^@].{service,socket,timer}'] }
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def get_changed_services(dir_a, dir_b, services)
|
|
|
|
services.select do |service|
|
|
|
|
a = File.join(dir_a, service)
|
|
|
|
b = File.join(dir_b, service)
|
|
|
|
(File.size(a) != File.size(b)) || (File.read(a) != File.read(b))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
TargetDirRegexp = /^(.*\.target)\.wants$/
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
# @return all units wanted by active targets
|
|
|
|
def get_active_targets_units(units_dir)
|
2017-12-04 10:17:46 +00:00
|
|
|
return Set.new unless Dir.exists?(units_dir)
|
|
|
|
targets = Dir.entries(units_dir).map { |entry| entry[TargetDirRegexp, 1] }.compact
|
|
|
|
active_targets = get_active_units(targets)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
active_units = active_targets.map do |target|
|
2017-12-04 10:17:46 +00:00
|
|
|
get_service_files(File.join(units_dir, "#{target}.wants"))
|
|
|
|
end.flatten
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
Set.new(active_units)
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# @return true on success
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
def run_cmd(*cmd)
|
2017-12-04 10:17:46 +00:00
|
|
|
print_cmd cmd
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
@dry_run || system(*cmd)
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
def systemctl_action(cmd, services)
|
2017-12-04 10:17:46 +00:00
|
|
|
return if services.empty?
|
|
|
|
|
|
|
|
verb = (cmd == 'stop') ? 'Stopping' : "#{cmd.capitalize}ing"
|
|
|
|
puts "#{verb}: #{services.join(' ')}"
|
|
|
|
|
|
|
|
cmd = ['systemctl', '--user', cmd, *services]
|
|
|
|
if @dry_run
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
puts cmd.join(' ')
|
2017-12-04 10:17:46 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
output, status = Open3.capture2e(*cmd)
|
|
|
|
print output
|
|
|
|
# Show status for failed services
|
|
|
|
unless status.success?
|
|
|
|
# Due to a bug in systemd, the '--user' argument is not always provided
|
|
|
|
output.scan(/systemctl (?:--user )?(status .*?)['"]/).flatten.each do |status_cmd|
|
|
|
|
puts
|
|
|
|
run_cmd("systemctl --user #{status_cmd}")
|
|
|
|
end
|
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
def systemctl(*cmd)
|
|
|
|
output, _ = Open3.capture2('systemctl', '--user', *cmd)
|
|
|
|
output
|
|
|
|
end
|
|
|
|
|
2017-12-04 10:17:46 +00:00
|
|
|
def print_cmd(cmd)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
puts [*cmd].join(' ') if @verbose || @dry_run
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def get_active_units(units)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
filter_units(units) { |state| state == 'active' }
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def get_inactive_units(units)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
filter_units(units) { |state| state != 'active' }
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_failed_units(units)
|
|
|
|
filter_units(units) { |state| state == 'failed' }
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
def filter_units(units)
|
2017-12-04 10:17:46 +00:00
|
|
|
return [] if units.empty?
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
states = systemctl('is-active', *units).split
|
|
|
|
units.select.with_index { |_, i| yield states[i] }
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_oneshot_services(units)
|
|
|
|
return [] if units.empty?
|
|
|
|
types = systemctl('show', '-p', 'Type', *units).split
|
2017-12-04 10:17:46 +00:00
|
|
|
units.select.with_index do |_, i|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
types[i] == 'Type=oneshot'
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_restricted_units(units)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
infos = systemctl('show', '-p', 'RefuseManualStart', '-p', 'RefuseManualStop', *units)
|
2017-12-04 10:17:46 +00:00
|
|
|
.split("\n\n")
|
|
|
|
no_manual_start = []
|
|
|
|
no_manual_stop = []
|
|
|
|
infos.zip(units).each do |info, unit|
|
|
|
|
no_start, no_stop = info.split("\n")
|
|
|
|
no_manual_start << unit if no_start.end_with?('yes')
|
|
|
|
no_manual_stop << unit if no_stop.end_with?('yes')
|
|
|
|
end
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
# Get units that should not be restarted even if a change has been detected.
|
|
|
|
no_restart_regexp = /^\s*X-RestartIfChanged\s*=\s*false\b/
|
|
|
|
no_restart = units.select { |unit| systemctl('cat', unit) =~ no_restart_regexp }
|
2019-04-14 00:04:52 +00:00
|
|
|
[no_manual_start, no_manual_stop, no_restart]
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def wait_and_get_failed_services(services, start_timeout_ms)
|
|
|
|
puts "Waiting #{start_timeout_ms} ms for services to fail"
|
|
|
|
# Force the previous message to always be visible before sleeping
|
|
|
|
STDOUT.flush
|
|
|
|
sleep(start_timeout_ms / 1000.0)
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
get_failed_units(services)
|
2017-12-04 10:17:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def show_failed_services_status(services)
|
|
|
|
puts
|
|
|
|
services.each do |service|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
run_cmd('systemctl', '--user', 'status', service)
|
2017-12-04 10:17:46 +00:00
|
|
|
puts
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def print_service_msg(msg, services)
|
|
|
|
return if services.empty?
|
|
|
|
if @verbose
|
|
|
|
puts "#{msg}:", services.to_a
|
|
|
|
else
|
|
|
|
puts msg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
systemd: improve systemd-activate.rb script
- Pass arguments verbatim to the `systemctl` subprocess, obviating the
need for shell escaping.
- Use open3 for capturing subprocess output.
- Fix printing of commands during dry run.
- Simplify `X-RestartIfChanged` regular expression.
1. Use \s to match whitespace, \b to match a word boundary.
2. Rename variable to conform to Ruby's underscore naming
conventions.
- Remove no-op set operation. Specifically, 'no_restart' and 'to_stop'
are disjunct since
1. After reloading the daemon with the new generation, units in
'to_stop' (i.e. units from the old gen that are missing in the
new gen) are not registered anymore in the systemd daemon.
2. Hence, 'systemctl cat' returns no output for these units.
3. Because this output is needed to detect 'no_restart' units,
'no_restart' includes no units from 'to_stop'.
So 'to_stop -= to_restart' is a no-op.
- Only notify about units that would otherwise be restarted. That is,
exclude units that are started but not restarted.
- Previously, all inactive units, like short-running services, were
handled as failed units.
Now systemd activation doesn't fail for oneshot services like
'setxkbmap' while 'servicesStartTimeoutMs' is set.
- Don't start unchanged oneshot services.
PR #1110
2020-03-23 06:49:44 +00:00
|
|
|
def notify_skipped_units(no_restart)
|
|
|
|
puts "Not restarting: #{no_restart.join(' ')}" unless no_restart.empty?
|
|
|
|
end
|
|
|
|
|
2017-12-04 10:17:46 +00:00
|
|
|
setup_services(*ARGV)
|