Equitable
Equitable

Reputation: 47

Is there a way to pipe IO?

I'm trying to pipe 2 IO object, i come from nodejs and we can do something like that:

const child_process = require('child_process')

const shell = child_process.spawn('/bin/sh')

shell.stdout.pipe(process.stdout)
shell.stdin.write('pwd\n')
shell.stdin.write('ls\n')
/* write all command i want */

and im looking for do the same thing in crystal

i know for the current example we can write

shell = Process.new("/bin/sh", input: Process::Redirect::Pipe, output: STDOUT, error: STDOUT)

shell.input << "ls\n"
shell.input << "pwd\n"
# all commands i want

but for some reason passing TCPSocket to Process.new input/output/error dont work very well (see here too if you have time Process and TCPSocket not close properly in crystal)

so im looking for an alternative way who will look like:

shell = Process.new("/bin/sh", input: Process::Redirect::Pipe, output: Process::Redirect::Pipe, Process::Redirect::Pipe)

shell.output.pipe(STDOUT) # not the crystal pipe but like the nodejs pipe

shell.input << "ls\n"
shell.input << "pwd\n"
# all commands i want

Upvotes: 1

Views: 345

Answers (1)

Jonne Ha&#223;
Jonne Ha&#223;

Reputation: 4857

You can use IO.copy inside a coroutine:

shell = Process.new("/bin/sh", input: :pipe, output: :pipe, error: :pipe)

spawn { IO.copy shell.output, STDOUT }
spawn { IO.copy shell.error, STDERR }

shell.input << "ls /\n"
shell.input << "pwd\n"

shell.wait

https://carc.in/#/r/75z4

Upvotes: 3

Related Questions