I have the following Ruby block:
ruby_block "Validate" do
block do
require "mixlib/shellout"
begin
cmd = Mixlib::ShellOut.new("/usr/local/bin/someScript.py", :timeout => 3600)
cmd.live_stream = STDOUT
cmd.run_command
cmd.error!
rescue Exception => e
puts "Action failed..."
return 168
end
end
action :create
notifies :create, "ruby_block[Validated]", :immediately
not_if { node[:state][:validated] == true }
end
I want to log the result of the script into both STDOUT and a file called "/tmp/xml_diff_results.txt".
The first thing I did was change:
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py", :timeout => 3600)
to:
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py > /tmp/xml_diff_results.txt", :timeout => 3600)
however, that did not do what I expected.
Then I noticed the cmd.live_stream
variable. Is there a way I can tap into that and do something like this?:
cmd.live_stream = (STDOUT > /tmp/xml_diff_results.txt)
SOLUTION:
The solution to my problem was simple and inspired by @tensibai.
log_file = File.open('/tmp/chef-run.log', File::WRONLY | File::APPEND)
LOG = Logger.new(log_file)
def shell(command)
LOG.info "Execute: #{command}"
cmd = Mixlib::ShellOut.new(command, :timeout => 1800)
cmd.run_command
LOG.info "Returned: #{cmd.stdout}"
cmd.error!
cmd
end
Another option in Ruby (just the inner part) in case tee
is not available (windows):
cmd = Mixlib::ShellOut.new("/usr/local/bin/someScript.py", :timeout => 3600)
cmd.live_stream = STDOUT
cmd.run_command
# new part
log=::Tempfile.new(["xml_diff_results",".txt"])
errlog=::File.open(log.path.gsub(".txt",".err")
log.write(cmd.stdout)
errlog.write(cmd.stderr)
log.close
errlog.close
Chef::Log.info("Log results are in #{log.path}")
# end of new part
cmd.error!
Change the Chef::Log
level to warn
if you run chef-client without -l info
and really want the path to be printed in chef log.
Main advantage is that it's platform independent, drawback is that the log files will only be written once the command has ended its execution.