[racket] Duplicating output from a system call

From: Nick Shelley (nickmshelley at gmail.com)
Date: Fri May 17 13:14:42 EDT 2013

I went to do my "tee" workaround that I assumed would work, and I
discovered that it suffers from the same issue. I then just ran the command
without Racket but included the pipe to tee and none of the output is shown
until the process finishes. The same thing happened when I pipe to less.
There's obviously something weird going on with that process and piping or
redirecting output that has nothing to do with Racket.

Also, thanks for the code Neil, I'll keep that in mind when I need to do
more intensive processing. My current needs are just to search the logs for
the presence of a "Fail:" string, which indicates a failure. I know the
problem is simple enough that I probably could have just piped to grep or
something, but I'm not very familiar or comfortable with command-line tools
and bash programming, and the last time I tried to do something like this
in bash, this unfamiliarity bit me a lot. Plus, I like finding
opportunities to use Racket at work so I can get paid to become more
familiar with a language I like using.

Thanks again for all the help. Sorry if my misdiagnosis of the problem
wasted anyone's time.


On Thu, May 16, 2013 at 11:01 PM, Neil Van Dyke <neil at neilvandyke.org>wrote:

> If you change the "process*" call in the below program to run your
> command, and run this program in DrRacket with "View -> Show Log",
> hopefully you see the output from your command promptly.
>
> #lang racket/base
>
> (require racket/system)
>
> (apply (lambda (stdout-in
>                 stdin-out
>                 pid
>                 stderr-in
>                 process-proc)
>          (let* ((buf-size  4096)
>                 (buf-bytes (make-bytes buf-size)))
>            (let loop ()
>              (let ((evt (sync/enable-break stdout-in stderr-in)))
>                ;; ...
>                (let ((read-result (read-bytes-avail! buf-bytes evt)))
>                  (cond ((eof-object? read-result)
>                         (log-error "EOF!")
>                         ;; ...
>                         (void))
>                        ;; ...
>                        (else
>                         (log-error "OUTPUT: ~S" (subbytes buf-bytes 0
> read-result))
>                         (loop))))))
>            ;; ...
>            (close-output-port stdin-out)
>            (close-input-port  stdout-in)
>            (close-input-port  stderr-in)))
>        (process* "/bin/sh"
>                  "-c"
>                  "while true ; do echo -n abc ; sleep 3 ; done"))
>
> (I wrote the code this particular way, using a bytes buffer, because it's
> a good starting point for doing fancier things, such as if you're trying to
> recognize particular output and handle it specially, or if you're
> interacting with the process.  This is as far as I can help, though.
>  Depending on the entirety of what you want to do with the output, getting
> this right can easily take hours and end up looking like systems
> programming.  Or you can look at doing it with first-class continuations,
> which should be more elegant, but continuations hurt people's brains
> initially, and i'm not sure how performance would compare.)
>
> Neil V.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130517/6f8b7b09/attachment.html>

Posted on the users mailing list.