Hey,

I don't have a comment on how *out* and *err* are implemented, but
here's a solution for your particular problem. Runtime/exec returns a
java.lang.Process [1] object which has getInputStream and
getOutputStream methods corresponding to System/out and System/err of
the spawned process respectively. So, grab those and fire off a couple
of futures to copy the streams to files. A very rough sketch:

(let [in (.getInputStream proc)]
  (future
     (clojure.java.io/copy in (clojure.java.io/output-stream
"output-file.txt"))))

repeat for getErrorStream.

In fact, when you're starting processes with exec you *always* want to
do something like this even if you're throwing away the output.
Otherwise the stdout buffer for the spawned process will eventually
fill up and it will block leaving you wondering why it randomly
stopped working.

HTH,

Dave

[1] http://download.oracle.com/javase/6/docs/api/java/lang/Process.html

On Wed, Sep 14, 2011 at 9:15 AM, Nick Mudge <[email protected]> wrote:
> I have a clojure program with which I would like all stdout and stderr
> to be written to a file.
>
> Of course there is Unix IO redirection but I am starting my program
> from within another clojure program using "(.exec (Runtime/getRuntime)
> clj-program-command env)" and that doesn't support IO redirection. Of
> course I could use the "bash -c" command within the command to start
> my program but it does make things a bit messier with all the quotes
> and escaping of quotes, and anyway I would like to achieve this
> objective within my clojure program.
>
> I found out that System/out and System/err are separate and different
> than *out* and *err*. Changing *out* or *err* does not change System/
> out or System/err. My program includes the Jetty server which is
> written in Java so it writes to System/out and System/err and not to
> *out* and *err*. So to change all stdout and stderr to write to a file
> I need to change System/out, System/err and *out* and *err*.
>
> I can do this like so in my core.clj file:
>
> (System/setOut (PrintStream. (FileOutputStream. "/home/user/myproject/
> log.txt" true) true))
> (System/setErr (PrintStream. (FileOutputStream. "/home/user/myproject/
> log.txt" true) true))
>
> (binding [*out* (java.io.PrintWriter. System/out)
>             *err*  (java.io.PrintWriter. System/err)]
>  (start-my-app))
>
> The only way I know of changing *out* and *err* is to wrap my entire
> program inside the "binding" function.
>
> I was wondering what is thought of the idea of making *out* and *err*
> dynamic vars? If they were dynamic I could do the following which I
> think is nicer and more elegant:
>
> (System/setOut (PrintStream. (FileOutputStream. "/home/user/myproject/
> log.txt" true) true))
> (System/setErr (PrintStream. (FileOutputStream. "/home/user/myproject/
> log.txt" true) true))
> (def *out* (java.io.PrintWriter. System/out))
> (def *err* (java.io.PrintWriter. System/err))
>
> Better yet, it would be nice if I changed *out* and *err* and that
> caused System/out and System/err to change too. So I could do:
>
> (def *out* (java.io.PrintWriter. (FileOutputStream. "/home/user/
> myproject/log.txt" true))
> (def *err* (java.io.PrintWriter. (FileOutputStream. "/home/user/
> myproject/log.txt" true))
>
> And System/out and System/err would also change.
>
> Thoughts?
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to