Execute external interactive command, get stdout and store stderr


I need to execute some commands and print stdout message, store stderr and raise(stderr) on any errors.

System used: OpenBSD
Commands used pkg_delete ; pkg_add
Output is interactive, so it writes directly to tty, no stdout

Commands behavior

  • Get status zero even the command fails
  • stderr is filled on error, so we can filter on this like stderr.empty? to know if there’s a failure
  • stdout empty except using system method but can’t store stderr
  • i can get stderr (not the full message) using Open3.capture3 but can’t get stdout

Can you help me? thanks!

Below a demo script with the outputs (=>) next to each command

# remove sl package
cmd = 'pkg_delete sl'

# add sl package
cmd2 = 'pkg_add sl'

# try with a bad package name
cmd3 = 'pkg_add sli'

# sample of commands
cmd = 'pkg_delete sl'
cmd2 = 'pkg_add sl'
cmd3 = 'pkg_add sli'

# using system method, can print stdout but no way to store stderr or stop on error
puts :system_cmd_remove
exit unless system(cmd) => sl-5.02: ok

puts :system_cmd2_add
exit unless system(cmd2) => sl-5.02: ok

puts :system_cmd3_bad
exit unless system(cmd3) => Cant find sli\nopen3_cmd_remove

# Using Open3.capture3, no stdout, can store stderr (not fully)
puts :open3_cmd_remove
stdout, stderr, status = Open3.capture3(cmd)
puts "stdout : #{stdout}" => stdout :
puts "stderr : #{stderr}" => stderr :
puts "status : #{status}" => status : pid 51369 exit 0

puts :open_cmd2_add
stdout, stderr, status = Open3.capture3(cmd2)
puts "stdout : #{stdout}" => stdout :
puts "stderr : #{stderr}" => stderr :
puts "status : #{status}" => status : pid 99908 exit 0

puts :open_cmd3_bad
stdout, stderr, status = Open3.capture3(cmd3)
puts "stdout : #{stdout}" => stdout :
puts "stderr : #{stderr}" => stderr : Cant find sli
puts "status : #{status}" => status : pid 24159 exit 0