Kevin, I tried to use your code, but I also need a pipe to gnuplot's stdin. If I understand correctly, `open_stdout_stderr` connects the commands' stdin to DevNul; this causes gnuplot to exit immediately after calling the function, since there is no way to send it any commands.
I tried modifying your function by just adding `in` and `cmd_in` pipes, linking them, and calling spawn as r = spawn(false, ignorestatus(cmd), (cmd_in, cmd_out, cmd_err)) but I am missing something: gnuplot keeps dying just after I call the function. Can you tell what I'm missing? My complete code is: function open_stdin_stdout_stderr(cmd::Cmd) in = Base.Pipe(C_NULL) out = Base.Pipe(C_NULL) err = Base.Pipe(C_NULL) cmd_in = Base.Pipe(C_NULL) cmd_out = Base.Pipe(C_NULL) cmd_err = Base.Pipe(C_NULL) Base.link_pipe(in, true, cmd_in, false) Base.link_pipe(out, true, cmd_out, false) Base.link_pipe(err, true, cmd_err, false) r = spawn(false, ignorestatus(cmd), (cmd_in, cmd_out, cmd_err)) Base.close_pipe_sync(cmd_out) Base.close_pipe_sync(cmd_err) Base.close_pipe_sync(cmd_in) # NOTE: these are not necessary on v0.4 (although they don't seem # to hurt). Remove when we drop support for v0.3. Base.start_reading(out) Base.start_reading(err) return (in, out, err, r) end On Thu, Jun 18, 2015 at 12:11 PM, Kevin Squire <kevin.squ...@gmail.com> wrote: > I don't think there's a standard way--at least, I couldn't find it when I > looked. I ended up rolling my own--see > https://github.com/kmsquire/VideoIO.jl/blob/master/src/util.jl. > > This functionality should probably be part of readandwrite. > > Cheers, > Kevin > > > On Thursday, June 18, 2015, Miguel Bazdresch <eorli...@gmail.com> wrote: > >> Is there a way to read the spawned process' STDERR? Gnuplot likes to >> write most output to it. I've tried >> >> readandwrite(`gnuplot 2>&1`) >> >> but gnuplot interprets 2>&1 as a filename and fails. >> >> This, however, works: >> >> readandwrite(`gnuplot` .> "/tmp/gnuplot.err") >> >> but I'd like to avoid having to create a file. >> >> Thanks! >> >> On Wed, Jun 17, 2015 at 1:05 PM, Kevin Squire <kevin.squ...@gmail.com> >> wrote: >> >>> `open(cmd, "w")` gives back a tuple. Try using >>> >>> f, p = open(`gnuplot`,"w") >>> write(f, "plot sin(x)") >>> >>> There was a bit of discussion when this change was made (I couldn't find >>> it with a quick search), about this returning a tuple--it's a little >>> unintuitive, and could be `fixed` in a few different ways (easiest: >>> returning a complex type that can be written to and read from), but it's >>> probably been off most people's radar. If you're up for it, why don't you >>> open an issue (if one doesn't exist). >>> >>> Anyway, for your particular application, you probably want >>> `readandwrite`: >>> >>> help?> readandwrite >>> search: readandwrite >>> >>> Base.readandwrite(command) >>> >>> Starts running a command asynchronously, and returns a tuple >>> (stdout,stdin,process) of the output stream and input stream of the >>> process, and the process object itself. >>> >>> Which *also* returns a tuple (but at least now you know). >>> >>> See also >>> http://blog.leahhanson.us/running-shell-commands-from-julia.html, which >>> has a full rundown of reading and writing from processes. >>> >>> Cheers! >>> Kevin >>> >>> On Wed, Jun 17, 2015 at 9:03 AM, Miguel Bazdresch <eorli...@gmail.com> >>> wrote: >>> >>>> Hello, >>>> >>>> Gaston.jl is a plotting package based on gnuplot. Gnuplot is >>>> command-line tool, so I send commands to it via a pipe. I open the pipe (on >>>> Linux) with a ccall to "popen", and write gnuplot commands to the pipe >>>> using a ccall to fputs. >>>> >>>> This works fine, but I'm trying to see if Julia's native pipe and >>>> stream functionality can make this process more Julian and, in the process, >>>> more cross-platform. The documentation is encouraging: >>>> >>>> "You can use [a Cmd] object to connect the command to others via pipes, >>>> run it, and read or write to it." and "Julia provides a rich interface to >>>> deal with streaming I/O objects such as terminals, pipes and TCP sockets." >>>> Unfortunately, I just can't figure out how to use Julia's functionality for >>>> this purpose. This is what I've tried (I am on Julia 0.3.9): >>>> >>>> First, I tried using `open` with read and write: >>>> >>>> julia> f=open(`gnuplot`,"r+") >>>> ERROR: ArgumentError("mode must be \"r\" or \"w\", not \"r+\"") >>>> >>>> So I tried with write only: >>>> >>>> julia> f=open(`gnuplot`,"w") >>>> (Pipe(open, 0 bytes waiting),Process(`gnuplot`, ProcessRunning)) >>>> >>>> So far, this looks good. I can see a gnuplot process running. >>>> >>>> Then I try to `write` to the pipe: >>>> >>>> julia> write(f,"plot sin(x)") >>>> ERROR: `write` has no method matching write(::(Pipe,Process), >>>> ::ASCIIString) >>>> >>>> OK, so let's try with `println`: >>>> >>>> julia> println(f,"plot sin(x)") >>>> (Pipe(open, 0 bytes waiting),Process(`gnuplot`, >>>> ProcessRunning))plot sin(x) >>>> >>>> and no plot is produced. >>>> >>>> I can't figure out how to read from the pipe, either: >>>> >>>> julia> readbytes(f) >>>> ERROR: `readbytes` has no method matching >>>> readbytes(::(Pipe,Process)) >>>> >>>> julia> readall(f) >>>> ERROR: `readall` has no method matching readall(::(Pipe,Process)) >>>> >>>> I'd appreciate any pointers. Thanks! >>>> >>>> -- mb >>>> >>>> >>> >>