here is a piece of my chef ruby code and I am trying to pass a value from one block to other block. We have multiple ports running on the server, below code will check the port and if its not running it will try to execute the 2nd block. I have attached the code and error. Please help where i am going wrong.
ports.each do |port|
bash "Check_port_running_#{port}" do
code <<-EOH
pidval=$(ps -ef | grep /opt/redis/src/redis-server | grep *:#{port} | grep -vc grep)
if (($pidval == 0));then
portval_#{port}=true
else
portval_#{port}=false
fi
EOH
end
bash "Starting_redis_after_crash_for_port - #{port}" do
only_if { "portval_#{port}" }
code <<-EOH
rm -f #{port}.pid
sudo service redis@#{port} start
EOH
end
end
Error : Getting below error
================================================================================
Error executing action `run` on resource 'bash[Starting_redis_after_crash_for_port - 54321]'
================================================================================
Errno::ENOENT
-------------
No such file or directory - portval_54321
Resource Declaration:
---------------------
# In /tmp/kitchen/cache/cookbooks/csg_orderservices_redis/recipes/configure.rb
184: bash "Starting_redis_after_crash_for_port - #{port}" do
185: only_if "portval_#{port}"
186: code <<-EOH
187: rm -f #{port}.pid
188: sudo service redis@#{port} start
189: EOH
190: end
191: end
Compiled Resource:
------------------
# Declared in /tmp/kitchen/cache/cookbooks/csg_orderservices_redis/recipes/configure.rb:184:in `block in from_file'
bash("Starting_redis_after_crash_for_port - 54321") do
action [:run]
default_guard_interpreter :default
backup 5
interpreter "bash"
declared_type :bash
cookbook_name "csg_orderservices_redis"
recipe_name "configure"
code " rm -f 54321.pid\n sudo service redis@54321 start\n"
domain nil
user nil
only_if "portval_54321"
end
My opinion would be to avoid using bash resources for this. This is to ensure your Chef recipes are idempotent, and can simplify your code as most of the heavy lifting is done by the Chef client. I only use bash, powershell, etc. resources as a last resort.
Here's my suggestion and example below:
Create a library file called redis.rb in your libraries folder within the cookbook. I prefer to namespace my libraries to help organize my methods. This redis_active? method can be used from anywhere in your cookbook where this module is included.
libraries/redis.rb:
# Replace CookbookName with actual cookbook name
module CookbookName
module Redis
include Chef::Mixin::ShellOut
def redis_active?(port)
cmd = "ps -ef | grep /opt/redis/src/redis-server | grep *:#{port} | grep -vc grep"
pid_exists = shell_out(cmd).stdout.strip.to_i
return true if pid_exists > 0
end
end
end
In your redis recipe, the file resource will only take action if the redis_active? method returns false for the specified port, and then file resource will converge and remove the pid file. When this resource converges, it will notify the service resource to restart the redis server service immediately.
recipes/redis.rb:
# Replace CookbookName with actual cookbook name
Chef::Resource::File.send(:include, CookbookName::Redis)
ports.each do |port|
file "/path/to/#{port}.pid" do
action :delete
not_if { redis_active?(port) }
notifies :restart, "service[redis@#{port}]", :immediately
end
service "redis@#{port}" do
action :nothing
end
end