Question

In Ruby, is it possible to prevent the standard input of a spawned child process from being attached to the terminal without having to capture the STDOUT or STDERR of that same process?

  • Backticks and x-strings (`...`, %x{...}) don't work because they capture STDIN.

  • Kernel#system doesn't work because it leaves STDIN attached to the terminal (which intercepts signals like ^C and prevents them from reaching my program, which is what I'm trying to avoid).

  • Open3 doesn't work because its methods capture either STDOUT or both STDOUT and STDERR.

So what should I use?

Was it helpful?

Solution

If you’re on a platform that supports it, you could do this with pipe, fork and exec:

# create a pipe
read_io, write_io = IO.pipe

child = fork do
  # in child

  # close the write end of the pipe
  write_io.close

  # change our stdin to be the read end of the pipe
  STDIN.reopen(read_io)

  # exec the desired command which will keep the stdin just set
  exec 'the_child_process_command'
end

# in parent

# close read end of pipe
read_io.close

# write what we want to the pipe, it will be sent to childs stdin
write_io.write "this will go to child processes stdin"
write_io.close

Process.wait child
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top