Search code examples
http-redirectterminaljuliaoutputstdio

Redirect stio and still printing in the terminal


Thanks to this great answer from @Przemyslaw Szufel, we can easily redirect stdio output into a file providing its path.

I wanted to know if it is possible to both redirect stio output to a file and still continue print it in the terminal. That is probably an easy feature to achieve but I could not find it! And obviously not running the code twice :)


Solution

  • You need a Tee Stream such as https://github.com/fredrikekre/TeeStreams.jl/. Unfortunately the interface of redirect_stdio does not accept abstract IO for its sink. It requires it to be an IOStream which is a concrete Julia type. So it seems like there is no good way with the redirect_stdio via streams.

    However redirect_stdio does accept sockets and named pipes and this is a way you could consider (yet too complex for this simple tasks - maybe someone finds a more elegant solution).

    First you need to create a pipe server that will be running asynchronously in your REPL session (this is code for Windows for Linux you will probably need to remove \\.\pipe\ from the pipe name):

    using Sockets 
    srv = Sockets.listen(raw"\\.\pipe\TeePipe")
    mystdout = stdout
    @async begin
        open("log.txt", "w") do f
           sock = accept(srv)
           while !eof(sock)
               line = readline(sock)
               println(mystdout, line)
               flush(mystdout)
               println(f, line)
               flush(f)
           end
        end    
    end
    

    Now at the same REPL session you create the client:

    teelogger = Sockets.connect(raw"\\.\pipe\TeePipe")
    

    And here is a sample REPL session showing that this works:

    julia> redirect_stdio(stdout=teelogger) do
                  println("Line1")
                  println("Line2")
                  @show 3+4
           end
    Line1
    Line2
    3 + 4 = 7
    7
    
    shell> more log.txt
    Line1
    Line2
    3 + 4 = 7