Skip to content

Documentation about tee #26

@borkdude

Description

@borkdude

The use case for tee is to redirect output to stdout but also to capture it in a file. We could make a built-in construct for this so you can use it to print to stdout but also capture the out stream.

(require '[babashka.process :refer [pipeline pb]]
         '[clojure.java.io :as io])

(let [[catp teep] (pipeline (pb ["cat"]) (pb ["tee" "log.txt"] {:out :inherit}))]
  ;; write to cat every 100 milliseconds 10 times
  (future
    (with-open [writer (io/writer (:in catp))]
      (loop [i 0]
        (when (< i 10)
          (binding [*out* writer]
            (println i)
            (flush))
          (Thread/sleep 100)
          (recur (inc i))))))

  @teep ;; wait for the tee process to finish
  ;; finally we print the file's content
  (println (slurp "log.txt")))

(shutdown-agents)

Also see https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/output/TeeOutputStream.html

This code is close but doesn't work yet:

(ns tee
  (:require [babashka.process :refer [process]]
            [clojure.java.io :as io])
  (:import [java.io InputStream]))

(defn tee [proc out-1 out-2]
  (let [^InputStream in (:out proc)
        ^java.lang.Process proc (:proc proc)]
    (loop [alive? (.isAlive proc) idx 0]
      (if-not alive?
        (recur (.isAlive proc) idx)
        (let [j (.available in)]
          (when (pos? j)
            (prn :read idx j)
            (let [buf (byte-array j)]
              (.read in buf idx j)
              (io/copy buf out-1)
              (io/copy buf out-2)))
          (when (.isAlive proc)
            (recur alive? (+ idx j))))))))

(def catp (process ["cat"]))

(future
  (with-open [writer (io/writer (:in catp))]
    (loop [i 0]
      (when (< i 10)
        (binding [*out* writer]
          (println i))
        (Thread/sleep 100)
        (recur (inc i))))))

(tee catp *out* *out*)

@catp

(shutdown-agents)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions