简体   繁体   English

如何将脚本输出记录到STDOUT和文件

[英]How to log script output to STDOUT and a file

I have the following Ruby block: 我有以下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

I want to log the result of the script into both STDOUT and a file called "/tmp/xml_diff_results.txt". 我想将脚本的结果记录到STDOUT和一个名为“ /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. 然后我注意到了cmd.live_stream变量。 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. 解决我的问题的方法很简单,并受到@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

This isn't a Ruby or even Chef question. 这不是Ruby甚至Chef的问题。 It's more like a Bash question 更像是Bash问题

One way to run a command, and redirect its output to stdout and a file, could be using tee 一种运行命令并将其输出重定向到stdout和文件的方法是使用tee

echo 'Hello World!' | tee output.log

So, with your example it could be like this 因此,以您的示例为例

cmd=Mixlib::ShellOut.new("/usr/local/bin/someScript.py | tee /tmp/xml_diff_results.txt", :timeout => 3600)

Another option in Ruby (just the inner part) in case tee is not available (windows): 如果tee不可用(窗口),则Ruby中的另一个选项(仅是内部):

  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. Chef::Log级别更改为warn如果您运行不带-l info chef-client并且确实希望在chef日志中打印路径。

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. 主要优点是它与平台无关,缺点是仅在命令结束执行后才写入日志文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM