How to reload systemd config?


#1

I have defined a systemd init config

  service 'solr' do
    provider Chef::Provider::Service::Systemd
    retries 5
    retry_delay 10
    action [:enable, :start]
  end

I notice in systemctl status solr.service it gives the following warning.

Warning: solr.service changed on disk. Run 'systemctl daemon-reload' to reload units.

Is there a native way to run daemon-reload with the service resource?

Looking at the ruby docs for action :reload it appears to run the following command

 systemctl reload foo

I don’t see a native way to do a daemon-reload.

What the correct way to run systemctl daemon-reload with chef? Do I need to do something like this?

  execute 'systemctl daemon-reload' do
    command 'systemctl daemon-reload'
    action :nothing
  end
  
  template '/etc/systemd/system/solr.service' do
    source 'systemd/solr.service.erb'
    owner 'root'
    group 'root'
    action :create
    notifies :run, 'execute[systemctl daemon-reload]', :immediately
    notifies :restart, 'service[solr]', :delayed
  end

  service 'solr' do
    provider Chef::Provider::Service::Systemd
    retries 5
    retry_delay 10
    action [:enable, :start]
  end

#2

https://docs.chef.io/resource_systemd_unit.html

systemd_unit ‘mything.service’ do
action :reload
end


#3

well if you use the systemd_unit resource, you get automatic reloads…

triggers_reload

Ruby Type: TrueClass, FalseClass

Specifies whether to trigger a daemon reload when creating or deleting a
unit. Default is true.


#4

The systemd_unit only takes a string for the content attribute.

My script is 50+ lines long. Am I expected to take that script and condense it into 1 line?

systemd_unit 'sysstat-collect.timer' do
  enabled true
  content '[Unit]\nDescription=Run system activity accounting tool every 10 minutes\n\n[Timer]\nOnCalendar=*:00/10\n\n[Install]\nWantedBy=sysstat.service'
end

#5

I totally agree. The content property is gross and there needs to be a way
to supply a file. I’ve been using heredocs, and it is far from ideal.

I’ll try to get a PR in in the next week or so


#6

again, not ideal, but it works until the systemd_unit resource gets an
update

class String
def strip_heredoc
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, “”.freeze)
end
end

systemd_unit ‘thing.service’ do
content <<-_EOH.strip_heredoc

_EOH
end


#7

the systemd_unit content property also takes a hash, fwiw, which is a much nicer way to structure unit content…

e.g.

systemd_unit 'sysstat-collect.timer' do
  content({
    'Unit' =>{
       'Description' => 'Run system activity accounting tool every 10 minutes'
    },
    'Timer' => {
       'OnCalendar' => '*:00/10'
    },
    'Install' => {
      'WantedBy' => 'sysstat.service'
    }})
    action [:create, :enable, :start]
end

there’s also the systemd cookbook, which goes quite a bit deeper, and maps unit properties to resource properties.


#8

My workaround for this is to use the reload_command option to the service resource for those cases where I’m altering an existing service or using more than a single config for the systemd_unit. In this case we are moving from docker-engine to docker-ce and needed to update a couple configs, and if either of the files was missing or empty systemctl would hang trying to restart docker during the install.

cookbook_file '/etc/systemd/system/docker.service.d/10-docker.conf' do
  source '10-docker.conf'
  notifies :reload, 'service[docker]', :immediately
  notifies :restart, 'service[docker]', :delayed
  not_if { ::File.exist?('/tmp/kitchen') }
end

cookbook_file '/etc/docker/daemon.json' do
  source 'daemon.json'
  notifies :reload, 'service[docker]', :immediately
  notifies :restart, 'service[docker]', :delayed
  not_if { ::File.exist?('/tmp/kitchen') }
end

docker_installation_package 'default' do
  action :create
  version node['docker']['version']
  package_options "--force-yes -o Dpkg::Options::='--force-confold' -o Dpkg::Options::='--force-all'"
end

service 'docker' do
  action :nothing
  reload_command 'systemctl daemon-reload'
end