How to Force Chef to Start a Service Regardless of Status Check


15 views

When working with Chef's service resource, you might encounter situations where the service status check incorrectly reports the service as running. This typically happens with services like PostgreSQL where the status command might return false positives. Here's what you're seeing in debug mode:

DEBUG: service[postgresql] supports status, running
DEBUG: service[postgresql] is running

Even when the service is actually stopped. This creates a scenario where standard Chef recipes fail to maintain service availability.

The conventional Chef pattern:

service "postgresql" do
    action :start
end

Relies on the service's status command, which in some cases can be unreliable. Chef's idempotency model means it won't attempt to start a service it believes is already running.

Option 1: Disable Status Checking

The most elegant solution is to configure Chef to ignore the service status:

service "postgresql" do
  supports :status => false
  action [:enable, :start]
end

This forces Chef to execute the start command every time, while still maintaining idempotency through the service manager.

Option 2: Use the :nothing Pattern

For more control, combine with a notification:

service "postgresql" do
  action :nothing
end

execute "always_start_postgres" do
  command "service postgresql start"
  notifies :start, 'service[postgresql]', :immediately
end

Option 3: Platform-Specific Implementation

For maximum reliability across different init systems:

service "postgresql" do
  start_command value_for_platform_family(
    "debian" => "/etc/init.d/postgresql start",
    "rhel" => "systemctl start postgresql",
    "default" => "service postgresql start"
  )
  supports :status => false
  action :start
end

When implementing these solutions:

  • Always test the status command manually on your target systems
  • Consider creating a custom lightweight resource for critical services
  • Monitor service state independently of Chef runs
  • Document any service-specific behaviors in your cookbook

To properly diagnose service resource problems:

chef-shell -z
recipe_mode
resources("service").each {|r| puts "#{r.name}: #{r.defined_actions}" }

This helps verify how Chef is interpreting your service definitions.


When dealing with services in Chef, particularly PostgreSQL, we often encounter situations where the service status check returns false positives. The standard Chef service resource behavior becomes problematic when:

service "postgresql" do
  action :start
end

This appears to work initially but fails to detect when the service has been stopped out-of-band, showing (up to date) in subsequent runs despite the service being down.

The debug output reveals the root cause:

DEBUG: service[postgresql] supports status, running
DEBUG: service[postgresql] is running

Even when the service is actually stopped, the status check incorrectly reports it as running. This typically happens when:

  • The service init script's status command is improperly implemented
  • The process is running but unresponsive
  • There are permission issues with status checks

Option 1: Using the :restart Action

While not ideal, this ensures the service comes up:

service "postgresql" do
  action :restart
end

Pros:

  • More portable than execute commands
  • Built-in Chef resource behavior

Cons:

  • Performs unnecessary stop/start cycle when service is already running
  • Might briefly interrupt connections

Option 2: Custom Status Command

Override the default status check:

service "postgresql" do
  supports :status => false
  start_command "/etc/init.d/postgresql start"
  action :start
end

Or more thoroughly:

service "postgresql" do
  status_command "pgrep -u postgres -f postgresql | grep -v grep"
  action :start
end

Option 3: Combined Approach

For maximum reliability across different platforms:

service "postgresql" do
  supports :restart => true, :status => false
  start_command "service postgresql start || /etc/init.d/postgresql start"
  stop_command "service postgresql stop || /etc/init.d/postgresql stop"
  restart_command "service postgresql restart || /etc/init.d/postgresql restart"
  action :start
end

For systemd-based systems (modern Linux distributions):

service "postgresql" do
  provider Chef::Provider::Service::Systemd
  action :start
end

For Upstart systems:

service "postgresql" do
  provider Chef::Provider::Service::Upstart
  action :start
end

Always verify with:

chef-client -l debug

And manually check service status:

ps aux | grep postgres
service postgresql status
systemctl status postgresql  # For systemd

Remember that service management behavior may vary across different PostgreSQL versions and OS distributions.