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.