Chef - execute vs bash resource - ruby

I used both the execute resource or the bash resource.
Both achieve the same result:
bash 'Execute my script' do
user 'root'
cwd '/mydir'
code <<-EOH
./myscript.sh
EOH
end
execute 'Execute my script' do
user 'root'
cwd '/mydir'
command './myscript.sh'
end
The only difference I see is that bash actually creates a shell script (named /tmp/chef-script#{date}{#id}) where code is written.
What is the best practice to execute a shell script with Chef between execute or bash resource ?

For a single script, use an execute. The bash resource is for including the script contents inline in the recipe code.

In bash & execute block we need to write code to catch the error as if you add more than one command & the chef takes the status of the last command.
To make it more clear - when the Bash/execute block has only one command chef catches the issue ,if the next command is successful then it takes the last command status.
bash 'Execute my script' do
user 'root'
cwd '/mydir'
code <<-EOH
./myscript.sh
ls srini ##This will fail
ls ## this will be successful
EOH
end
execute 'Execute my script' do
user 'root'
cwd '/mydir'
command './myscript.sh'
command 'ls srini' #will fail
command 'ls' # will be successful
end

Related

output of unix command in chef recipe

I have an execute command in a chef recipe, and I'd like to set the cwd property as the output of a unix command.
execute 'run dynamically generated install file' do
command 'make install'
cwd '' # would like the output of `ls -Adrt /tmp/unixODBC.* | tail -n 1`
end
Is this possible?
Okay, so finally at a keyboard and can write this out in full.
The literal translation of what you have there would be:
execute 'run dynamically generated install file' do
command 'make install'
cwd lazy { shell_out!('ls -Adrt /tmp/unixODBC.* | tail -n 1').stdout.strip }
end
However that is going to be much slower than needed and more failure prone so I would recommend writing it in Ruby instead:
execute 'run dynamically generated install file' do
command 'make install'
cwd lazy { Dir['/tmp/unixODBC.*'].first }
end
This avoids having to spawn a bunch of processes and instead just does the same (I think) logic directly.
You should be able to do it just like this:
execute 'run dynamically generated install file' do
command 'make install'
cwd `ls -Adrt /tmp/unixODBC.* | tail -n 1`
end
That seems like it's out of the scope of an execute block.
Maybe just use a ruby_block?
ruby_block 'run dynamically generated install file' do
require 'mixlib/shellout'
block do
cmd = Mixlib::ShellOut.new('make install')
cmd.run_command
cwd = cmd.stdout
# Do more stuff with cwd...
end
end

Jenkins fails with Execute shell script

I have my bash script in ${JENKINS_HOME}/scripts/convertSubt.sh
My job has build step Execute shell:
However after I run job it fails:
The error message (i.e. the 0: part) suggests, that there is an error while executing the script.
You could run the script with
sh -x convertSubt.sh
For the safe side, you could also do a
ls -l convertSubt.sh
file convertSubt.sh
before you run it.
make sure that the script exist with ls
no need to sh , just ./convertSubs.sh ( make sure you have run permissions)

Chef run sh script

I have a problem trying to run shell script via Chef (with docker-provisioning).
This is how I try to execute my script:
bash 'shell_try' do
user "root"
run = "#{some_path_to_script}/my_script.sh some_params"
code " #{run} > stdout.txt 2> stderr.txt"
end
(note that this script should run another scripts, processes and write logs)
Here's no errors in the output, but when I log into machine and run ps aux process isn't running.
I guess something wrong with permissions (or env variables), because when I try the same command manually - it works.
A bash resource just runs the provided script text directly, if you wanted to run a long-running process generally you would set up an Upstart or systemd service and use the service resource to start it.
Finally find a solution (thanks to #coderanger) -
Install supervisor:
Download supervisor cookbook
Add:
include_recipe 'supervisor::default'
Add my service to supervisor:
supervisor_service "name" do
action :enable
#action :start
command '/path/script.sh start'
end
Run supervisor service
All done!
Please see the Chef documentation for your resource: https://docs.chef.io/resource_bash.html. The bash resource does not support a run attribute. Text of the code attribute is run as a bash script. The default action is to run the script unless told otherwise by the resource.
bash 'shell_try' do
user "root"
code " #{run} > stdout.txt 2> stderr.txt"
action :run
end
The code attribute is written to a temporary file where it is then run using the attributes specified in the resource.
The line run = "#{some_path_to_script}/my_script.sh some_params" at this point does nothing.

How to achieve idempotence when we execute bash script in ruby/knife environment?

I am trying to execute bash script in knife/Ruby environment. For example:
cookbook_file "test.sh" do
path "/tmp/test.sh"
mode "755"
action :create
end
bash "execute test.sh on #{nodeName}" do
code <<-EOH
sh test.sh arg1 arg2
EOH
#only_if { false }
end
How can I use only_if or not_if? So when we execute second time and the contents of "test.sh" is not changed, it should skip execution. I am getting this:
* cookbook_file[test.sh] action create (up to date)
but it still executes second time, third time...
You wouldn't use a guard, instead you would use a notification:
execute 'run test' do
action :nothing
command 'bash /tmp/test.sh arg1 arg2'
end
cookbook_file "test.sh" do
path "/tmp/test.sh"
mode "755"
notifies :run, 'execute[run test]', :immediately
end
Notifications trigger when a resources updates, so any time the cookbook file changes, it will run the execute. Also you want to be using execute instead of bash or script because you are running a command rather than an inline script file.

Chef shell script not being run

I am using Chef on Scalarium to download an agent and run various commands on it. What I'm attempting is to write a shell script in the recipe to perform this.
file "/etc/profile.d/blah.sh" do
content <<-EOH
sudo -sH
<Retrieve file and run some commands>
EOH
end
When I run the recipe in Scalarium, no errors occur, but the commands aren't run either. There's no errors in the commands themselves, as I've run them on my computer.
The recipe is definitely read, as the Chef logs contain Processing file[/etc/profile.d/blah.sh] on blah.localdomain.
I've never used Chef before, do I need to do something else to tell it to execute the shell script?
Perhaps you want something like:
file "/etc/profile.d/blah.sh" do
mode 0500
content <<-EOH
sudo -sH
<Retrieve file and run some commands>
EOH
end
execute "/etc/profile.d/blah.sh"
Or, you can put the file retrieval and running of commands directly into your chef recipe:
remote_file "/path/to/where/the/file/should/be/saved" do
source "https://example.com/path/to/where/the/file/comes/from"
end
execute "first command"
execute "second command"

Resources