如何将脚本输出记录到 STDOUT 和文件
How to log script output to STDOUT and a file
我有以下 Ruby 块:
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
我想将脚本的结果记录到 STDOUT 和名为“/tmp/xml_diff_results.txt”的文件中。
我做的第一件事就是改变:
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py", :timeout => 3600)
至:
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py > /tmp/xml_diff_results.txt", :timeout => 3600)
然而,这并没有达到我的预期。
然后我注意到 cmd.live_stream
变量。有没有办法让我利用它并做这样的事情?:
cmd.live_stream = (STDOUT > /tmp/xml_diff_results.txt)
解决方案:
我的问题的解决方案很简单,灵感来自@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
这不是 Ruby 甚至大厨的问题。这更像是一个 Bash 问题
运行 命令并将其输出重定向到标准输出和文件的一种方法是使用 tee
echo 'Hello World!' | tee output.log
因此,对于您的示例,它可能是这样的
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py | tee /tmp/xml_diff_results.txt", :timeout => 3600)
Ruby 中的另一个选项(只是内部部分)以防 tee
不可用(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!
如果您 运行 没有 -l info
的 chef-client 并且真的希望在 chef 日志中打印路径,请将 Chef::Log
级别更改为 warn
。
主要优点是它与平台无关,缺点是只有在命令结束执行后才会写入日志文件。
我有以下 Ruby 块:
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
我想将脚本的结果记录到 STDOUT 和名为“/tmp/xml_diff_results.txt”的文件中。
我做的第一件事就是改变:
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py", :timeout => 3600)
至:
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py > /tmp/xml_diff_results.txt", :timeout => 3600)
然而,这并没有达到我的预期。
然后我注意到 cmd.live_stream
变量。有没有办法让我利用它并做这样的事情?:
cmd.live_stream = (STDOUT > /tmp/xml_diff_results.txt)
解决方案:
我的问题的解决方案很简单,灵感来自@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
这不是 Ruby 甚至大厨的问题。这更像是一个 Bash 问题
运行 命令并将其输出重定向到标准输出和文件的一种方法是使用 tee
echo 'Hello World!' | tee output.log
因此,对于您的示例,它可能是这样的
cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py | tee /tmp/xml_diff_results.txt", :timeout => 3600)
Ruby 中的另一个选项(只是内部部分)以防 tee
不可用(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!
如果您 运行 没有 -l info
的 chef-client 并且真的希望在 chef 日志中打印路径,请将 Chef::Log
级别更改为 warn
。
主要优点是它与平台无关,缺点是只有在命令结束执行后才会写入日志文件。