Suppressing Command Prompt output while running a shell command in capture3

114 Views Asked by At

I'm running Amazon's Kindle Previewer tool in a Ruby script through capture3. The Kindle Previewer command validates an epub file and prints a log to a specified folder, while also printing a log in the terminal as it runs. I do not want any of these messages to appear in the terminal though. The syntax for the command itself is kindlepreviewer [epub file] -log -output [log output folder]. Within my capture3 statement, it looks like this:

stdout, stderr, status = Open3.capture3("kindlepreviewer #{epub_file} -log -output #{output_folder}")

This executes successfully on both a Mac and a PC, and I'm able to use the output elsewhere in my script. On a Mac, the Terminal window suppresses the output that is generated while the command is running, which is what I want. My problem is that in Windows, all of the output still comes through in Command Prompt. I can't figure out how to turn this off. Based on similar questions such as: Suppressing the output of a command run using 'system' method while running it in a ruby script, I tried something like:

stdout, stderr, status = Open3.capture3("#{cmd} #{epub} -log -output #{@kindle_folder} > /dev/null 2>&1")

This has no effect at all. The executes normally, with all output still appearing in Command Prompt.

I know Kindle Previewer is a very specific tool to be referencing here, but I can't seem to find a more general answer as to why running a capture3 command on a Mac will suppress the output in Terminal, but running it in Windows Command Prompt will not. Is there a different way I should be running shell commands in Ruby on a PC, while still being able to store the command's output in the script?

1

There are 1 best solutions below

0
On

I was struggling with a similar problem myself, where I wanted to completely prevent any console output on Windows. Remember that the Windows DOS prompt is not a Bash shell, so you really cannot use the same output redirection syntax.

After trying several different options, I ended up using win32/process, which gives direct access to the Win32 API CreateProcess method. Only using this approach was I able to fully prevent ouput:

require 'win32/process'

pinfo = Process.create({ command_line:   "program arguments",
                         creation_flags: Process::DETACHED_PROCESS })

# Taken from the win32/process manual, in case you need to wait for the
# spawned process to finish before continuing with the rest of your script:
sleep 0.1 while !Process.get_exitcode(pinfo.process_id)

DETACHED_PROCESS here is key, as it prevents any access to the originating terminal by the created process.

Use gem install win32-process to install this gem.