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
>>>>
>>>>
>>>
>>

Reply via email to