JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.68k stars 5.48k forks source link

pipeline(cmd, stdout = file, stderr = file) works like a typical shell (not a bug) #45767

Open tpapp opened 2 years ago

tpapp commented 2 years ago
julia> versioninfo()
Julia Version 1.8.0-rc1
Commit 6368fdc656* (2022-05-27 18:33 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 8 on 8 virtual cores
Environment:
  JULIA_NUM_THREADS = 1
  JULIA_CMDSTAN_HOME = /home/tamas/src/cmdstan/

julia> logfile = mktemp()[1]
"/tmp/jl_9xswDp"

julia> print(read("/tmp/test.sh", String))
#!/bin/bash
echo "This message goes to stdout"
echo "This message goes to stderr" >&2

julia> run(pipeline(`/tmp/test.sh`; stdout = logfile, stderr = logfile))
Process(`/tmp/test.sh`, ProcessExited(0))

julia> read(logfile, String)
"This message goes to stderr\n"
tpapp commented 2 years ago

(append = true is a workaround, but that may not be what the user wants)

vtjnash commented 2 years ago

I am not certain what you were expecting here, since any sane shell would do exactly the same thing:

$ (echo hi ; echo bye >&2) > "logfile" 2> "logfile"
$ cat logfile 
bye

Your error is in using mktemp()[1] instead of [2].

giordano commented 2 years ago

You may be interested in OutputCollectors.jl. Example from the readme:

julia> using OutputCollectors

julia> script = """
       #!/bin/sh
       echo 1
       sleep 1
       echo 2 >&2
       sleep 1
       echo 3
       sleep 1
       echo 4
       """
"#!/bin/sh\necho 1\nsleep 1\necho 2 >&2\nsleep 1\necho 3\nsleep 1\necho 4\n"

julia> oc = OutputCollector(`sh -c $script`; verbose = true);

julia> [22:42:30] 1
[22:42:31] 2
[22:42:32] 3
[22:42:33] 4
julia>

julia> merge(oc)
"1\n2\n3\n4\n"

julia> merge(oc; colored = true)
"1\n\e[31m2\n\e[39m3\n4\n"

julia> tail(oc; len = 2)
"3\n4\n"

julia> collect_stdout(oc)
"1\n3\n4\n"

julia> collect_stderr(oc)
"2\n"
tpapp commented 2 years ago

@vtjnash: I was expecting a redirection of both streams into the same file, or at least an error if that cannot be done.

Like a lot of users, I am not familiar with the fine details of redirection and pipes. Cf #35959.

I recognize that for some people with the relevant knowledge this is expected behavior; for the rest of us an error or a warning would be helpful, or at least mention in the docs that one should use streams, etc.