0

I have a Ruby script that I have developed that allows me to install and build multiple C++ packages. I am able to execute the Ruby script and install the packages with no errors.

However, I would like to be able to capture all of the output, including cerr, to a "log" file of my choosing. I am able to redirect Ruby's cerr and standard output, but I cannot capture the bash commands: qmake, make, or make install cerr. The output still flows to the terminal.

I want to be able to run the Ruby script and not see any debug messages from any qmake, make, or make install bash commands, but be able to check a log file later for build results.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303

4 Answers4

2

you can do

require 'open3'

log = File.new("#{your_log_dir}/script.log", "w+")
command = "make"

Open3.popen3(command) do |stdin, stdout, stderr|
     log.puts "[OUTPUT]:\n#{stdout.read}\n"
     unless (err = stderr.read).empty? then 
          log.puts "[ERROR]:\n#{err}\n"
     end
end
saihgala
  • 5,724
  • 3
  • 34
  • 31
  • Can I use this with multiple commands? ie: command = "make" || "qmake" || "make install" – user1612173 Aug 20 '12 at 16:19
  • you can put all your commands in an array and loop through it e.g. `commands = ["make","qmake","make install"]; commands.each do |command| Open3.popen3(command) do |stdin, stdout, stderr| ....` – saihgala Aug 20 '12 at 16:21
  • Works, except for program freezing at #{stdout.read} I am also needing to pass svn parameters in to a few of the source files that are building. Is this creating a loop between svn output waiting for user input, and the open3 loop waiting for stdout? – user1612173 Aug 20 '12 at 16:59
  • what do you mean by freezing at `stdout.read`? I use such a block to execute all sorts of external commands - `javac, java, msbuild, p4 etc.` without any issues ever. I'll be able to help further after reading your code to see whats going on? – saihgala Aug 21 '12 at 07:43
  • can you tick my answer if you found it useful? – saihgala Aug 23 '12 at 07:25
0

%x[#insert bash command here] captures the response. If you need to handle STDERR you'll want to pipe it to STDOUT I believe.

Ryanmt
  • 3,215
  • 3
  • 22
  • 23
0

To directly dump stdout and stderr of a child process to files:

cmd = ['ls', '-ahl', '/my/directory'] # example directory listing
pid = Process.spawn *cmd, out: '/path/to/stdout/log', err: '/path/to/stderr/log'
Process.wait pid

You may also pass file descriptors instead of path strings.

Catnapper
  • 1,875
  • 10
  • 12
0

If you're on Mac OS or Linux, you can use standard redirection and a simple shell call if you want to capture the STDOUT and STDERR to a variable in your script:

asdf = `ls foo 2>&1`
asdf # => "ls: foo: No such file or directory\n"

2>&1 simply redirects STDERR in the command output to STDOUT, which is captured when the program runs.

If you want to redirect both STDOUT and STDERR to the same file for later, use:

`ls foo > output.log 2>&1`

The STDOUT has to be redirected before &2>1 will take effect, but that will capture both.

For more information see the "Redirect" section of man sh.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303